如何使用Java实现给绳子或线段画颜色的算法

场景 要实现一个绳子染色的功能的算法
如图:

img


一开始是一个红色线段,两端坐标分别为0和100,画上一个蓝色线段后,红色线段被截断,变成红蓝红三个线段

点 对象 使用 String表示
线段对象 Line {
String start;
String end
}
线段集合是List ,要求尽可能用Java stream实现画新颜色的draw函数

一段线能否重复染色,是否只有红蓝两色,

已解决

/**
 * 老师考勤计算过程
 *
 */

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
/**
 * 考勤计算过程
 * @author chenlinhui
 *
 */
public class TeacherAttCalculationPress  {
    
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate = format.parse("2021-10-11 00:00:00");
        Date endTime = format.parse("2021-10-12 00:00:00");
        TeacherAttCalculationPress press = new TeacherAttCalculationPress(startDate, endTime, AttType.WEI_CHU_QIN, "");

        System.err.println("初始化时间轴》》" + press.attList);
        TeacherAttUnit attUnitNew1 = new TeacherAttUnit();
        attUnitNew1.setStartTime(format.parse("2021-10-11 09:00:00"));
        attUnitNew1.setEndTime(format.parse("2021-10-11 15:00:00"));
        attUnitNew1.setAttType(AttType.CHU_QIN);
        attUnitNew1.setLeaveType("");
        press.insert(attUnitNew1);
        System.err.println("增加出勤》》" + press.attList);
        TeacherAttUnit attUnitNew = new TeacherAttUnit();
        attUnitNew.setStartTime(format.parse("2021-10-11 12:00:00"));
        attUnitNew.setEndTime(format.parse("2021-10-11 18:00:00"));
        attUnitNew.setAttType(AttType.CHU_QIN);
        attUnitNew.setLeaveType("");
        press.insert(attUnitNew);
        System.err.println("增加交叉出勤》》" + press.attList);
        TeacherAttUnit attUnitNew2 = new TeacherAttUnit();
        attUnitNew2.setStartTime(format.parse("2021-10-11 16:00:00"));
        attUnitNew2.setEndTime(format.parse("2021-10-11 17:00:00"));
        attUnitNew2.setAttType(AttType.NIAN_JIA);
        attUnitNew2.setLeaveType("");
        press.insert(attUnitNew2);
        System.err.println("增加年假》》" + press.attList);
    }
    private List<TeacherAttUnit>  attList; //每个时段的集合
    /**
     * 初始化计算过程
     * @param startTime   时间轴开始时间
     * @param endTime     时间轴结束时间
     * @param attType     时间轴默认考勤状态
     * @param leaveType   时间轴默认请假状态
     */
    public TeacherAttCalculationPress(Date startTime,Date endTime,AttType attType, String leaveType){
        attList = new LinkedList<TeacherAttUnit>();
        TeacherAttUnit attTeacherAttUnit = new TeacherAttUnit();
        attTeacherAttUnit.setStartTime(startTime);
        attTeacherAttUnit.setEndTime(endTime);
        attTeacherAttUnit.setAttType(attType);
        attTeacherAttUnit.setLeaveType(leaveType);
        attTeacherAttUnit.attTypeList.add(attType);
        attList.add(attTeacherAttUnit);
    }
    //原有数据  2021年9月01日 到2021年9月29日  出勤
    //插入数据  2021年9月09日 到 2021年9月19日  类型请假
    //结果      2021年9月01日 到2021年9月29日  出勤,  2021年9月29日  到   2021年9月09日  请假,  2021年9月09日 到 2021年9月19日  出勤
    /**
     * 添加一个假单,第一个添加的假单时间区间是最大需要处理的时间区间
     * @param attUnitNew  新加的考勤单元或者假单
     */
    public void insert(TeacherAttUnit attUnitNew) {
        if (attList == null) {
            attList = new LinkedList<TeacherAttUnit>();
        }
        if (attList.size() == 0) {
            attList.add(attUnitNew);
            return;
        }
        //步骤1. 进行线段染色,染色后会出现相邻线段相同颜色情况,下一步需要合并
        attList = attList.stream().flatMap((attNode)->{

            SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss" );
            List<TeacherAttUnit>  flatList =  new  ArrayList<>();
            //以下处理只保留attNode覆盖的时段,所以要求alllist中第一个节点是覆盖全天的
            /**
             * att                                  ------------
             * 情况一    └───────────────────────┘
             * 互相无交叉
             *   */
            if (attNode.getStartTime().compareTo(attUnitNew.getEndTime()) >= 0
                    ||attNode.getEndTime().compareTo(attUnitNew.getStartTime()) <= 0) {
                flatList.add(attNode);
            }
            /**
             * att         ------------
             * 情况二    └───────────────────────┘
             * 新的包含已有的
             *   */
            else if (attUnitNew.getStartTime().compareTo(attNode.getStartTime()) <= 0
                    && attUnitNew.getEndTime().compareTo(attNode.getEndTime()) >= 0) {
                attNode.getAttTypeList().add(attUnitNew.attType);
                if (attNode.getAttType().sort < attUnitNew.getAttType().sort) {
                    attNode.setAttType(attUnitNew.attType);
                }
                flatList.add(attNode);
            }
            /**
             * att    ------------------------------
             * 情况三               └──────────────┘
             * 已有的包含新的
             *   */
            else if (attUnitNew.getStartTime().compareTo(attNode.getStartTime()) > 0
                    && attUnitNew.getEndTime().compareTo(attNode.getEndTime()) < 0) {

                if (attNode.getAttType().sort < attUnitNew.getAttType().sort) {
                    //新插入优先级高,时间段被分割成三个时间段
                    TeacherAttUnit attNew_1 = new TeacherAttUnit();
                    attNew_1.setStartTime(attNode.getStartTime());
                    attNew_1.setEndTime(attUnitNew.getStartTime());
                    attNew_1.setAttType(attNode.getAttType());
                    attNew_1.getAttTypeList().addAll(attNode.attTypeList);
                    
                    TeacherAttUnit attNew_2 = new TeacherAttUnit();
                    attNew_2.setStartTime(attUnitNew.getStartTime());
                    attNew_2.setEndTime(attUnitNew.getEndTime());
                    attNew_2.setAttType(attUnitNew.getAttType());
                    attNew_2.getAttTypeList().addAll(attNode.attTypeList);
                    attNew_2.getAttTypeList().add(attUnitNew.attType);
                    
                    TeacherAttUnit attNew_3 = new TeacherAttUnit();
                    attNew_3.setStartTime(attUnitNew.getEndTime());
                    attNew_3.setEndTime(attNode.getEndTime());
                    attNew_3.setAttType(attNode.getAttType());
                    attNew_3.getAttTypeList().addAll(attNode.attTypeList);

                    flatList.add(attNew_1);
                    flatList.add(attNew_2);
                    flatList.add(attNew_3);
                }else {
                    //保持不变
                    attNode.getAttTypeList().add(attUnitNew.attType);
                    flatList.add(attNode);
                }
                
            }
            /**
             * att                 ------------------------------
             * 情况四    └───────────────────────┘
             * 交叉一
             *   */
            else if (attUnitNew.startTime.compareTo(attNode.startTime) <= 0
                     && attUnitNew.endTime.compareTo(attNode.startTime) > 0
                     && attUnitNew.endTime.compareTo(attNode.endTime) < 0) {

                if (attNode.getAttType().sort < attUnitNew.getAttType().sort) {
                    //新插入优先级高,时间段被分割成两个时间段
                    
                    TeacherAttUnit attNew_2 = new TeacherAttUnit();
                    attNew_2.setStartTime(attNode.getStartTime());
                    attNew_2.setEndTime(attUnitNew.getEndTime());
                    attNew_2.setAttType(attUnitNew.getAttType());
                    attNew_2.getAttTypeList().addAll(attNode.attTypeList);
                    attNew_2.getAttTypeList().add(attUnitNew.attType);
                    
                    TeacherAttUnit attNew_3 = new TeacherAttUnit();
                    attNew_3.setStartTime(attUnitNew.getEndTime());
                    attNew_3.setEndTime(attNode.getEndTime());
                    attNew_3.setAttType(attNode.getAttType());
                    attNew_3.getAttTypeList().addAll(attNode.attTypeList);

                    flatList.add(attNew_2);
                    flatList.add(attNew_3);
                }else {
                    //保持不变
                    attNode.getAttTypeList().add(attUnitNew.attType);
                    flatList.add(attNode);
                }
                
            }
            /**
             * att    ------------------------------
             * 情况五                                      └───────────────────────┘
             * 交叉二
             *   */
            else if (attUnitNew.startTime.compareTo(attNode.startTime) > 0
                    && attUnitNew.startTime.compareTo(attNode.endTime) < 0
                    && attUnitNew.endTime.compareTo(attNode.endTime) >= 0) {

                if (attNode.getAttType().sort < attUnitNew.getAttType().sort) {
                    //新插入优先级高,时间段被分割成两个时间段

                    TeacherAttUnit attNew_3 = new TeacherAttUnit();
                    attNew_3.setStartTime(attNode.getStartTime());
                    attNew_3.setEndTime(attUnitNew.getStartTime());
                    attNew_3.setAttType(attNode.getAttType());
                    attNew_3.getAttTypeList().addAll(attNode.attTypeList);
                    
                    TeacherAttUnit attNew_2 = new TeacherAttUnit();
                    attNew_2.setStartTime(attUnitNew.getStartTime());
                    attNew_2.setEndTime(attNode.getEndTime());
                    attNew_2.setAttType(attUnitNew.getAttType());
                    attNew_2.getAttTypeList().addAll(attNode.attTypeList);
                    attNew_2.getAttTypeList().add(attUnitNew.attType);
                    

                    flatList.add(attNew_2);
                    flatList.add(attNew_3);
                }else {
                    //保持不变
                    attNode.getAttTypeList().add(attUnitNew.attType);
                    flatList.add(attNode);
                }
            }
            return flatList.stream();
        })
        
        //步骤2.排序,为 合并相邻的相同颜色的线段 做准备
        .sorted((sortNode1,sortNode2) -> {
                //按时间排序
                return sortNode1.getStartTime().compareTo(sortNode2.getStartTime());
            })
        //步骤3:使用规约方法,比较相邻元素,进行合并操作
        .reduce(new ArrayList<TeacherAttUnit>(),  (result,attNode)->{
                //跟最后一个元素相同就合并,不同就添加
                if (result.size() >0 && result.get(result.size() - 1).attType.sort == attNode.attType.sort) {
                    //合并操作,也就是修改最后一个节点结束时间,
                    result.get(result.size() - 1).setEndTime(attNode.getEndTime());
                }else {
                    result.add(attNode);
                }
                
                return result;
            },(a,b) -> a);
    }
    /**
     * 计算并返回考勤结果
     * @return  计算完的考勤结果
     */
    public String  calculationResult() {
        
        return attList.toString();
    }
}