# -*- coding: utf-8 -*-
"""
Created on Sun Dec  6 14:47:32 2020

@author: user
"""

import random as rd
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
rd.seed(2022)


truckCapacity = 200

class Node(object):
    def __init__(self, nid, x, y, demand):
        self.nid = nid
        self.x = x
        self.y = y
        self.demand = demand
    def __str__(self):
        return f"nid={self.nid}, x={self.x}, y={self.y}, demand={self.demand}"
    __repr__=__str__
    
class Arc(object):
    def __init__(self, aid=None, na=None, nb=None):
        self.aid = aid
        self.na = na
        self.nb = nb
        self.length = self.__length()
    
    def __length(self):
        return ((self.na.x-self.nb.x)**2+(self.na.y-self.nb.y)**2)**0.5
    
    def __str__(self):
        return f"aid = {self.aid}\n{self.na}\n{self.nb}\nlength={self.length}\n"
    
    __repr__ = __str__

class Graph(object):
    def __init__(self, route:list):
        self.nodes = [Node(i, rd.randint(0,100), rd.randint(0,100), rd.randint(10,20)) for i in range(1, 51)]
        self.nodes.insert(0, Node(0, 50, 50, 0))
        with open("VRPnodes.txt", 'w') as f:
            for n in self.nodes:
                f.write(f"{n}\n")
        
        self.totalLoad = 0        
        self.arcs = []
        for a in self.nodes:
            row = [Arc(aid=(a.nid, b.nid), na = a, nb = b) for b in self.nodes]
            self.arcs.append(row) 
            self.totalLoad+=a.demand
        
        print(f"客戶總荷重為{self.totalLoad}")
        
        
        ## file of arcs
        with open("VRParcs.txt", 'w') as f:
            for row in self.arcs:
                for arc in row:
                    f.write(f"{arc}\n")
                f.write(f"\n\n")
        
        ## excel for arc length
        df = pd.DataFrame(np.zeros((len(self.nodes), len(self.nodes))))
        for rid, row in enumerate(self.arcs):
            for cid, arc in enumerate(row):
                df.iloc[rid, cid] = arc.length
        df.to_csv('VRPArcLength.xls')
        
        self.route = route ##[0, 1,2,3,..., 0]
        if len(set(self.route)) != len(self.nodes):
            print(f"錯誤: 你必須服務所有客戶({len(set(self.route))}<{len(self.nodes)})。")
            print("-------------------------------------------------")
        self.nTruck = 0
        for i, n in enumerate(self.route):
            if i==0:
                load = 0
                continue
            if n!=0:
                load += self.nodes[n].demand
            else:
                self.nTruck += 1
                print(f"車輛 {self.nTruck} 荷重 = {load}")
                if load > truckCapacity:
                    print(f"錯誤: 車輛荷重不可大於{truckCapacity}")
                load = 0
                
            
        self.gPlot()
    
    def __routeLength(self)->float:
        rLength = 0
        for i in range(len(self.route)-1):
            fromNodeId = self.route[i]
            toNodeId = self.route[i+1]
            rLength += self.arcs[fromNodeId][toNodeId].length
        return rLength
    
    def gPlot(self):
        """
        * To plot the routes 
        """
        # rid = ["Truck"]
#        idcount = 0
        linestyles = ['-','--','-.',':']
#        markers = ['o','^','s','.','v','*','p','1','<','>','x','X','d','D','+']
        plt.figure(figsize = (12,12))
        # plt.title(f"Objective={objective}\nTotal cost={totalCost}\nMax Route={maxRoute}\nMax Min Difference={difference}")
        length = self.__routeLength()
        plt.title(f"Length={length}\nCost={length+self.nTruck*1000}")
        plt.grid(True)
        plt.minorticks_on()
        
        for n in self.nodes:
            if n.nid == 0:
                plt.plot(n.x, n.y, "bo", ms = 10)
            else:
                plt.plot(n.x, n.y, "gs")
            plt.text(n.x + 0.5, n.y + 0.5, f"{n.nid}({n.demand})")
            
        # tx = []
        # ty = []

        # for i in self.route:
        #     tx.append(self.nodes[i].x)
        #     ty.append(self.nodes[i].y)
        
        # plt.plot(tx,ty, "r-") ## plot truck route
        
        for i in range(len(self.route)-1):
            fId = self.route[i]
            tId = self.route[i+1]
            if fId==0:
                linecolor = np.random.rand(3)
                ls = rd.choice(linestyles)
            plt.plot((self.nodes[fId].x, self.nodes[tId].x), (self.nodes[fId].y, self.nodes[tId].y), color=linecolor, linestyle = ls)
        
        # plt.legend(rid)



if __name__=="__main__":
    
    
    ## 每一車輛的最大容量為200單位
    ## 每點的需求量可由圖中點編號後面之括號看出，亦可參考產生的nodes.txt檔案
    ## 將路徑輸入在此，使用逗點(,)分隔。
    route = [0,1,2,3,4,5,6,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,0,
             7,9,8,10,11,0,
             12,13,14,15,16,0]

    g = Graph(route)
    
    






