예제 #1
0
    def intervalRunStayTime(self,graph,start,end):
        """
        不算起点和终点
        """
        started = False
        running = 0
        stay = 0
        former = None

        for st in self.timetable:
            if stationEqual(st["zhanming"],start):
                started = True

            if not started:
                continue

            if former is None:
                former = st
                continue
            running += (st["ddsj"] - former["cfsj"]).seconds
            thisStay=(st["cfsj"] - st["ddsj"]).seconds
            if st["zhanming"] not in (start,end):
                stay += thisStay
            former = st
            if stationEqual(st["zhanming"],end):
                break
        # print(running, stay)
        return running, stay
예제 #2
0
 def jointTrain(self,train,former:bool,graph):
     """
     将train连接到本车次上。
     """
     if former:
         for st in reversed(train.timetable):
             if not graph.stationInLine(st["zhanming"]):
                 continue  #非本线站点不处理,以免出错
             find = False
             for node in self.timetable:
                 if stationEqual(st["zhanming"],node["zhanming"],strict=True):
                     find = True
                     break
             if find:
                 continue
             self.timetable.insert(0,st)
     else:
         for st in train.timetable:
             if not graph.stationInLine(st["zhanming"]):
                 continue  #非本线站点不处理,以免出错
             find = False
             for node in self.timetable:
                 if stationEqual(st["zhanming"],node["zhanming"],strict=True):
                     find = True
                     break
             if find:
                 continue
             self.timetable.append(st)
예제 #3
0
 def getInfo(self, fazhan, daozhan) -> dict:
     for node in self._nodes:
         if stationEqual(node["fazhan"], fazhan) and stationEqual(
                 node["daozhan"], daozhan):
             return node
     if not self._different:
         for node in self._nodes:
             if stationEqual(node["daozhan"], fazhan) and stationEqual(
                     node["fazhan"], daozhan):
                 return node
     return None
예제 #4
0
    def _find_neighbors(self, name: str):
        neighbors = []
        for st in self._nodes:
            if stationEqual(st["fazhan"], name):
                neighbors.append(st["daozhan"])

        if not self._different:
            for st in self._nodes:
                if stationEqual(st['daozhan'], name):
                    neighbors.append(st["fazhan"])

        return neighbors
예제 #5
0
 def intervalCount(self,graph,start,end):
     count = 0
     started=False
     for st in self.timetable:
         name = st["zhanming"]
         if stationEqual(name,start):
             started=True
         if not started:
             continue
         if graph.stationInLine(name):
             count+=1
         if stationEqual(name,end):
             break
     return count
예제 #6
0
 def stationBefore(self,st1,st2):
     """
     返回st1是否在st2之前。
     """
     findStart = False
     for st_dict in self.timetable:
         if stationEqual(st1,st_dict['zhanming']):
             findStart = True
         if stationEqual(st2,st_dict['zhanming']):
             if findStart:
                 return True
             else:
                 return False
     return False
예제 #7
0
 def checkStartEnd(self, train):
     # 返回False,True保留到最后
     if self.useStart:
         for st in self.startStations:
             if stationEqual(train.sfz, st):
                 break
         else:
             return False
     if self.useEnd:
         for st in self.endStations:
             if stationEqual(train.zdz, st):
                 break
         else:
             return False
     return True
예제 #8
0
 def intervalStopCount(self,graph,start,end):
     count = 0
     started = False
     for st in self.timetable:
         name = st["zhanming"]
         if stationEqual(name,start):
             started = True
         if not started:
             continue
         if graph.stationInLine(name) and (st["cfsj"]-st["ddsj"]).seconds!=0 and\
             name not in (start,end):
             count+=1
         if stationEqual(name,end):
             break
     return count
예제 #9
0
    def localRunStayTime(self, graph) -> (int, int):
        """
        计算本线纯运行时间的总和、本线停站时间总和。算法是从本线入图点开始,累加所有区间时分。
        2.0版本修改:计算所有【运行线铺画区段】的上述数值。区段包括首末站。不铺画运行线的区段不累计。
        """
        started = False
        n = 0  # 即将开始的铺画区段
        running = 0
        stay = 0
        former = None

        bounds = []
        for dct in self.itemInfo():
            bounds.append((dct['start'], dct['end']))
        if not bounds:
            return 0, 0
        # if self.fullCheci() == 'K1156/7':
        #     print(bounds)
        for st in self.timetable:
            if not started and stationEqual(
                    st['zhanming'], bounds[n][0], strict=True):
                # if self.fullCheci() == 'K8361/4/1':
                #     print("start seted to True",st['zhanming'])
                started = True
            if not started:
                continue
            if former is None:
                former = st
                stay += (st["cfsj"] - st["ddsj"]).seconds
                continue
            running += (st["ddsj"] - former["cfsj"]).seconds
            stay += (st["cfsj"] - st["ddsj"]).seconds
            # if self.fullCheci() == 'K8361/4/1':
            #     print("train.runStayTime",running,stay,former['zhanming'],st['zhanming'],n)
            former = st
            if stationEqual(st['zhanming'], bounds[n][1], strict=True):
                if n < len(bounds) - 1 and stationEqual(
                        st['zhanming'], bounds[n + 1][0]):
                    # if self.fullCheci() == 'K1156/7':
                    #     print("end but go on",st['zhanming'])
                    pass
                else:
                    started = False
                    former = None
                n += 1
                if n >= len(bounds):
                    break
        return running, stay
예제 #10
0
 def updateLocalFirst(self,graph):
     for st in self.timetable:
         name = st["zhanming"]
         for station in graph.line.stations:
             if stationEqual(name,station["zhanming"]):
                 self._localFirst = name
                 return name
예제 #11
0
 def postorderLinked(self,train)->tuple:
     """
     [Train,datetime] or [None,None]
     返回后续连接的车次。如果没有后续或者后续没有勾选link,返回None.
     """
     found = False
     postTrain = None
     for node in self.nodes():
         if node.train() is train:
             found=True
             continue
         if found:
             if not node.link:
                 return None,None
             else:
                 postTrain = node.train()
                 break
     if postTrain is None:
         return None,None
     thisEnd = train.destination()
     postStart = postTrain.departure()
     if thisEnd is None or postStart is None:
         return None,None
     if stationEqual(thisEnd['zhanming'],postStart['zhanming']) and \
         self.graph.stationInLine(thisEnd['zhanming']):
         return postTrain,postStart['cfsj']
     return None,None
예제 #12
0
    def preorderLinked(self,train)->tuple:
        """
        [Train,datetime] or [None,None]
        返回有Link的前一个车次及其终到时间。如果本车次没有Link,则返回None。
        返回的充要条件是符合连线条件。
        关于本交路长度的线性算法。
        """
        preNode = None
        preTrain = None
        for node in self.nodes():
            if node.train() is train:
                if preNode is None:
                    return None,None
                elif not node.link:
                    return None,None
                else:
                    preTrain = preNode.train()
                    break
            preNode = node
        if preTrain is None:
            return None,None
        preEnd = preTrain.destination()
        thisStart = train.departure()

        if preEnd is None or thisStart is None:
            return None,None
        if stationEqual(preEnd['zhanming'],thisStart['zhanming']) and \
            self.graph.stationInLine(preEnd['zhanming']):
            return preTrain,preEnd['ddsj']
        return None,None
예제 #13
0
 def stationIndexByName(self,name,strict=False)->int:
     """
     2.0新增。线性算法。
     """
     for i,st in enumerate(self.timetable):
         if stationEqual(st['zhanming'],name):
             return i
     return -1
예제 #14
0
 def stationIndex_bf(self,name:str):
     """
     原来的暴力方法查找序号。分离此函数是为了尝试统计有多少次使用暴力方法。
     """
     for i, st in enumerate(self.stations):
         if stationEqual(st["zhanming"], name):
             return i
     raise StationNotInLineException(name)
예제 #15
0
 def stationDict(self,name,strict=False):
     """
     线性算法
     """
     for st in self.timetable:
         if stationEqual(st["zhanming"],name,strict):
             return st
     return None
예제 #16
0
 def isDownGap(self, st1: str, st2: str):
     """
     判断给定的区间是否为下行区间
     """
     s1 = None
     s2 = None
     for st in self.stations:
         if stationEqual(st["zhanming"], st1):
             s1 = st
         elif stationEqual(st["zhanming"], st2):
             s2 = st
         if s1 is not None and s2 is not None:
             break
     try:
         if s1["licheng"] - s2["licheng"] > 0.0:
             return False
     except:
         pass
     return True
예제 #17
0
 def onStationDirectionSplited(self, old_name: str, down_name: str,
                               up_name: str):
     """
     2019.11.28新增。
     在将一个站拆成上下行两个站且没有动Line数据时调用。
     """
     if not self.different():
         self.setDifferent(True)
     for node in self._nodes:
         if stationEqual(node['fazhan'], old_name, strict=True):
             if self._line.isDownGap(node['fazhan'], node['daozhan']):
                 node['fazhan'] = down_name
             else:
                 node['fazhan'] = up_name
         elif stationEqual(node['daozhan'], old_name, strict=True):
             if self._line.isDownGap(node['fazhan'], node['daozhan']):
                 node['daozhan'] = down_name
             else:
                 node['daozhan'] = up_name
예제 #18
0
 def updateLocalLast(self,graph):
     """
     2019.02.03修改:时间换空间,计算并维护好数据。原函数名: localLast
     """
     for st in reversed(self.timetable):
         name = st["zhanming"]
         for station in graph.line.stations:
             if stationEqual(name,station["zhanming"]):
                 self._localLast = name
                 return name
예제 #19
0
    def gapBetweenStation(self,st1,st2,graph=None)->int:
        """
        返回两站间的运行时间
        :param graph:依赖的线路。不为None表示允许向前后推断邻近站。
        :return: seconds:int
        """
        st_dict1,st_dict2 = None,None
        for dict in self.timetable:
            if stationEqual(st1,dict['zhanming']):
                st_dict1 = dict
            elif stationEqual(st2,dict['zhanming']):
                st_dict2 = dict
        print("detect",self.fullCheci(),st1,st2)
        if st_dict1 is None or st_dict2 is None:
            if graph is None:
                raise Exception("No such station gap.",st1,st2)
            else:
                ignore_f = [st1,st2]
                station = st1
                while st_dict1 is None:
                    station = graph.adjacentStation(station,ignore_f)
                    print("adjacent found",station,ignore_f)
                    ignore_f.append(station)
                    if station is None:
                        break
                    st_dict1 = self.stationDict(station)
                print("st_dict1 found",st_dict1)

                ignore_l = [st1,st2]
                station = st2
                while st_dict2 is None:
                    station = graph.adjacentStation(station,ignore_l)
                    ignore_l.append(station)
                    if station is None:
                        break
                    st_dict2 = self.stationDict(station)
        if st_dict1 is None or st_dict2 is None:
            return -1 # no such gap

        dt = st_dict2["ddsj"]-st_dict1["cfsj"]
        return dt.seconds
예제 #20
0
 def destination(self) -> dict:
     """
     如果时刻表最后一个站是终到站,返回。否则返回None。
     """
     if not self.timetable:
         return None
     if not self.zdz:
         return None
     dct = self.timetable[-1]
     if stationEqual(dct['zhanming'], self.zdz):
         return dct
     return None
예제 #21
0
    def getInfo(self, fazhan: str, daozhan: str, allow_multi=False):
        """
        allow_multi:是否允许跨区间。
        """
        for node in self._nodes:
            if stationEqual(node['fazhan'],fazhan,strict=True) and \
                    stationEqual(node['daozhan'],daozhan,strict=True):
                return node

        for node in self._nodes:
            if stationEqual(node['fazhan'], fazhan) and stationEqual(
                    node['daozhan'], daozhan):
                return node

        if not self._different:
            for dict in self._nodes:
                if dict["fazhan"] == daozhan and dict["daozhan"] == fazhan:
                    return dict
            for node in self._nodes:
                if stationEqual(node['daozhan'], fazhan) and stationEqual(
                        node['fazhan'], daozhan):
                    return node

        if allow_multi:
            return self._multiBFS(fazhan, daozhan)

        return None
예제 #22
0
    def setStationDeltaTime(self,name:str,ds_int):
        st_dict = None
        for st in self.timetable:
            if stationEqual(st["zhanming"],name):
                st_dict = st
                break

        if st_dict is None:
            raise Exception("No such station",name)

        dt = timedelta(days=0,seconds=ds_int)
        st_dict["ddsj"] += dt
        st_dict["cfsj"] += dt
예제 #23
0
 def departure(self) -> dict:
     """
     如果时刻表第一个站是始发站,返回它。否则返回None。
     适用于严格要求判断始发站的场景,如交路连接。
     """
     if not self.timetable:
         return None
     if not self.sfz:
         return None
     dct = self.timetable[0]
     if stationEqual(dct['zhanming'], self.sfz):
         return dct
     return None
예제 #24
0
 def onStationDirectionSplited(self, old_name: str, down_name: str,
                               up_name: str):
     """
     2019.11.28添加。
     当站名被按上下行拆分时调用。
     precondition: Line中站名没有修改。
     只需要改名字,不需要插入新的结点。
     """
     self.resetAllPassed()
     if not self.different():
         self.setDifferent(True, True)
         print("Ruler::onStationDirectionSplited: 自动设为上下行分设标尺。")
     for node in self._nodes:
         if stationEqual(node['fazhan'], old_name, strict=True):
             if self._line.isDownGap(node['fazhan'], node['daozhan']):
                 node['fazhan'] = down_name
             else:
                 node['fazhan'] = up_name
         elif stationEqual(node['daozhan'], old_name, strict=True):
             if self._line.isDownGap(node['fazhan'], node['daozhan']):
                 node['daozhan'] = down_name
             else:
                 node['daozhan'] = up_name
예제 #25
0
    def _multiBFS(self, start, end):
        """
        BFS框架搜索从start到end的路径
        """
        length_dict = {}
        last_dict = {}  #记住每个站路径中的上一个站,方便回溯
        queue = []
        for w in self._find_neighbors(start):
            length_dict[w] = self.getInfo(start, w,
                                          allow_multi=False)['interval']
            last_dict[w] = start
            queue.append(w)

        while queue:
            v = queue.pop(0)
            if stationEqual(v, end):
                #找到要找的结点,直接返回
                interval = length_dict[v]  #区间运行时分
                t = last_dict[v]
                stop = self.getInfo(t, v)['stop']
                while last_dict[v] != start:
                    v = last_dict[v]
                # 现在v的last就是start
                start = self.getInfo(start, v)['start']
                return {
                    'interval': interval,
                    'start': start,
                    'stop': stop,
                }

            for w in self._find_neighbors(v):
                if w not in length_dict.keys():  # w is unreached
                    length_dict[w] = length_dict[v] + self.getInfo(
                        v, w, False)['interval']
                    last_dict[w] = v
                    queue.append(w)
        return None
예제 #26
0
 def stationInTimetable(self,name:str,strict=False):
     return bool(filter(lambda x:stationEqual(name,x,strict),
                        map(lambda x:x['zhanming'],self.timetable)))