Browse Source

Report version 1

develop
LO Kam Tao Leo 4 years ago
parent
commit
d67d1ba568
  1. 234
      src/org/leolo/rail/report/BasicTrainScheduleEntry.java
  2. 740
      src/org/leolo/rail/report/ReportGenerator.java
  3. 35
      src/org/leolo/rail/report/TrainRunningRecord.java
  4. 76
      src/org/leolo/rail/report/TrainRunningRecordEntry.java
  5. 105
      src/org/leolo/rail/report/TrainScheduleEntry.java

234
src/org/leolo/rail/report/BasicTrainScheduleEntry.java

@ -0,0 +1,234 @@
package org.leolo.rail.report;
import java.util.HashSet;
import org.leolo.rail.model.ScheduleType;
public class BasicTrainScheduleEntry {
private String suid;
private String trainUid;
private ScheduleType scheduleType;
private String signalId;
private String toc;
private String trainClass;
private String origin;
private long originTime;
private String destination;
private long destinationTime;
private long departTime;
private String departPlatform;
private long arriveTime;
private String arrivePlatform;
private HashSet<BasicTrainScheduleEntry> assoicatedEntry = new HashSet<>();
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((arrivePlatform == null) ? 0 : arrivePlatform.hashCode());
result = prime * result + (int) (arriveTime ^ (arriveTime >>> 32));
result = prime * result + ((assoicatedEntry == null) ? 0 : assoicatedEntry.hashCode());
result = prime * result + ((departPlatform == null) ? 0 : departPlatform.hashCode());
result = prime * result + (int) (departTime ^ (departTime >>> 32));
result = prime * result + ((destination == null) ? 0 : destination.hashCode());
result = prime * result + (int) (destinationTime ^ (destinationTime >>> 32));
result = prime * result + ((origin == null) ? 0 : origin.hashCode());
result = prime * result + (int) (originTime ^ (originTime >>> 32));
result = prime * result + ((scheduleType == null) ? 0 : scheduleType.name().hashCode());
result = prime * result + ((signalId == null) ? 0 : signalId.hashCode());
result = prime * result + ((suid == null) ? 0 : suid.hashCode());
result = prime * result + ((toc == null) ? 0 : toc.hashCode());
result = prime * result + ((trainClass == null) ? 0 : trainClass.hashCode());
result = prime * result + ((trainUid == null) ? 0 : trainUid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BasicTrainScheduleEntry other = (BasicTrainScheduleEntry) obj;
if (arrivePlatform == null) {
if (other.arrivePlatform != null)
return false;
} else if (!arrivePlatform.equals(other.arrivePlatform))
return false;
if (arriveTime != other.arriveTime)
return false;
if (assoicatedEntry == null) {
if (other.assoicatedEntry != null)
return false;
} else if (!assoicatedEntry.equals(other.assoicatedEntry))
return false;
if (departPlatform == null) {
if (other.departPlatform != null)
return false;
} else if (!departPlatform.equals(other.departPlatform))
return false;
if (departTime != other.departTime)
return false;
if (destination == null) {
if (other.destination != null)
return false;
} else if (!destination.equals(other.destination))
return false;
if (destinationTime != other.destinationTime)
return false;
if (origin == null) {
if (other.origin != null)
return false;
} else if (!origin.equals(other.origin))
return false;
if (originTime != other.originTime)
return false;
if (scheduleType != other.scheduleType)
return false;
if (signalId == null) {
if (other.signalId != null)
return false;
} else if (!signalId.equals(other.signalId))
return false;
if (suid == null) {
if (other.suid != null)
return false;
} else if (!suid.equals(other.suid))
return false;
if (toc == null) {
if (other.toc != null)
return false;
} else if (!toc.equals(other.toc))
return false;
if (trainClass == null) {
if (other.trainClass != null)
return false;
} else if (!trainClass.equals(other.trainClass))
return false;
if (trainUid == null) {
if (other.trainUid != null)
return false;
} else if (!trainUid.equals(other.trainUid))
return false;
return true;
}
public String getSuid() {
return suid;
}
public ScheduleType getScheduleType() {
return scheduleType;
}
public String getSignalId() {
return signalId;
}
public String getToc() {
return toc;
}
public String getTrainClass() {
return trainClass;
}
public String getOrigin() {
return origin;
}
public long getOriginTime() {
return originTime;
}
public String getDestination() {
return destination;
}
public long getDestinationTime() {
return destinationTime;
}
public HashSet<BasicTrainScheduleEntry> getAssoicatedEntry() {
return assoicatedEntry;
}
public void setSuid(String suid) {
this.suid = suid;
}
public void setScheduleType(ScheduleType scheduleType) {
this.scheduleType = scheduleType;
}
public void setSignalId(String signalId) {
this.signalId = signalId;
}
public void setToc(String toc) {
this.toc = toc;
}
public void setTrainClass(String trainClass) {
this.trainClass = trainClass;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public void setOriginTime(long originTime) {
this.originTime = originTime;
}
public void setDestination(String destination) {
this.destination = destination;
}
public void setDestinationTime(long destinationTime) {
this.destinationTime = destinationTime;
}
public String getTrainUid() {
return trainUid;
}
public void setTrainUid(String trainUid) {
this.trainUid = trainUid;
}
public long getDepartTime() {
return departTime;
}
public String getDepartPlatform() {
return departPlatform;
}
public long getArriveTime() {
return arriveTime;
}
public String getArrivePlatform() {
return arrivePlatform;
}
public void setDepartTime(long departTime) {
this.departTime = departTime;
}
public void setDepartPlatform(String departPlatform) {
this.departPlatform = departPlatform;
}
public void setArriveTime(long arriveTime) {
this.arriveTime = arriveTime;
}
public void setArrivePlatform(String arrivePlatform) {
this.arrivePlatform = arrivePlatform;
}
}

740
src/org/leolo/rail/report/ReportGenerator.java

@ -0,0 +1,740 @@
package org.leolo.rail.report;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.leolo.rail.DatabaseManager;
import org.leolo.rail.model.ScheduleType;
public class ReportGenerator {
public static Logger log = LogManager.getLogger(ReportGenerator.class);
public static final String SQL_1 = "SELECT \r\n" +
" lts.suid suid, lts.train_uid uid, lts.sch_type sch_type, lts.signal_id signal_id, lts.atoc_code toc,\r\n" +
" lts.train_category train_category, \r\n" +
" tiploc_to_crs(lts.origin) origin, TIME_TO_SEC(lts.origin_time) origin_time,\r\n" +
" tiploc_to_crs(lts.destination) destination, TIME_TO_SEC(lts.destination_time) destination_time,\r\n" +
" TIME_TO_SEC(al1.pub_departure) pub_departure, al1.platform dPlat,\r\n"+
" TIME_TO_SEC(al3.pub_arrival) pub_arrival, al3.platform aPlat\r\n"+
" FROM\r\n" +
" ltp_location al1\r\n" +
" LEFT JOIN ltp_location al3 ON al1.suid = al3.suid AND al1.seq < al3.seq\r\n" +
" LEFT JOIN ltp_schedule lts ON al1.suid = lts.suid\r\n" +
" LEFT JOIN tiploc tipo ON lts.origin = tipo.tiploc_code\r\n" +
" LEFT JOIN tiploc tipd ON lts.destination = tipd.tiploc_code \r\n" +
" WHERE\r\n" +
" 1=1\r\n" +
" AND al1.tiploc_code IN (SELECT tiploc_code FROM tiploc WHERE stanox IN (SELECT stanox FROM tiploc WHERE crs = ?))\r\n" +
" AND al3.tiploc_code IN (SELECT tiploc_code FROM tiploc WHERE stanox IN (SELECT stanox FROM tiploc WHERE crs = ?))\r\n" +
" AND ? BETWEEN lts.start_date AND lts.end_date\r\n" +
" AND lts.days LIKE get_wd_str(?)\r\n" +
" AND al1.pub_departure IS NOT null\r\n" +
" AND al3.pub_arrival IS NOT NULL";
public static final String LATEX_PREMBLE_1 = "\\documentclass[a4paper]{article}\r\n" +
"\\usepackage{tocloft}\r\n" +
"\\usepackage[utf8]{inputenc}\r\n" +
"\\usepackage[margin=0.675in]{geometry}\r\n" +
"\\usepackage[colorlinks = true]{hyperref}\r\n" +
"\\usepackage{color}\r\n" +
"\\usepackage{colortbl}\r\n" +
"\\usepackage[british]{babel}\r\n" +
"\\usepackage{longtable}\r\n" +
"\\usepackage{textcomp}\r\n" +
"\\usepackage{fancyhdr}\r\n" +
"\\usepackage{ulem}\r\n" +
"\\usepackage{array}\r\n" +
"\r\n" +
"\\pagestyle{fancy}\r\n" +
"\r\n" +
"\\newcommand{\\hr}{\\noindent\\hrulefill}\r\n" +
"\\newcommand{\\dfa}{\\cftdotfill{2}}\r\n" +
"\\newcommand{\\dfb}{\\cftdotfill{4}}\r\n" +
"\\newcommand{\\pa}{\\textit{(PASS)}}\r\n" +
"\\renewcommand\\cftsecleader{\\cftdotfill{\\cftdotsep}}\r\n" +
"\r\n" +
"\\setcounter{secnumdepth}{1}\r\n" +
"\\setcounter{tocdepth}{1}\r\n" +
"\r\n" +
"\\definecolor{hl1}{gray}{0.9}\r\n" +
"\\definecolor{hl2}{gray}{0.8}\r\n" +
"\r\n" +
"\\definecolor{e1}{rgb}{0,0,1}\r\n" +
"\\definecolor{ot}{rgb}{0,0,0}\r\n" +
"\\definecolor{l1}{rgb}{1.0,0.33,0.33}\r\n" +
"\\definecolor{l2}{rgb}{1.0,0,0}\r\n" +
"\\definecolor{l3}{rgb}{0.67,0,0}";
public static void main(String [] args) throws ParseException, IOException {
final String ORIGIN = "RDG";
final String DESTINATION = "PAD";
final java.util.Date RPT_DATE = new java.text.SimpleDateFormat("yyyy-MM-dd").parse("2022-03-16");
generateLaTeX(ORIGIN, DESTINATION, RPT_DATE);
}
public static File generateLaTeX(String origin, String destination, java.util.Date rptDate) throws IOException{
log.atInfo().log("{} -> {} on {}", origin, destination, rptDate);
TreeSet<String> tocList = new TreeSet<>();
TreeSet<String> tcList = new TreeSet<>();
TreeSet<String> locList = new TreeSet<>();
HashMap<String, String> tocCache = new HashMap<>();
HashMap<String, String> tcCache = new HashMap<>();
HashMap<String, String> locCache = new HashMap<>();
TreeSet<BasicTrainScheduleEntry> trains = new TreeSet<>(new Comparator<BasicTrainScheduleEntry>() {
@Override
public int compare(BasicTrainScheduleEntry arg0, BasicTrainScheduleEntry arg1) {
int val = Long.compare(arg0.getDepartTime(), arg1.getDepartTime());
if(val!=0) return val;
val = Long.compare(arg0.getArriveTime(), arg1.getArriveTime());
if(val!=0) return val;
return Integer.compare(arg0.getScheduleType().ordinal(), arg1.getScheduleType().ordinal());
}
});
TreeSet<TrainScheduleEntry> trainGroup = new TreeSet<>(new Comparator<TrainScheduleEntry>() {
@Override
public int compare(TrainScheduleEntry arg0, TrainScheduleEntry arg1) {
int val = Long.compare(arg0.getDepartTime(), arg1.getDepartTime());
if(val!=0) return val;
val = Long.compare(arg0.getArriveTime(), arg1.getArriveTime());
if(val!=0) return val;
return Integer.compare(arg0.getScheduleType().ordinal(), arg1.getScheduleType().ordinal());
}
});
HashMap<String, TrainScheduleEntry> trainGroups = new HashMap<>();
java.sql.Date sqlDate = new java.sql.Date(rptDate.getTime());
locList.add(origin);
locList.add(destination);
//Stage 1: get the basic train information for trains
try(
Connection conn = DatabaseManager.getInstance().getConnection();
PreparedStatement pstmt = conn.prepareStatement(SQL_1)
){
pstmt.setString(1, origin);
pstmt.setString(2, destination);
pstmt.setDate(3, sqlDate);
pstmt.setDate(4, sqlDate);
try(ResultSet rs = pstmt.executeQuery()){
int rowCount = 0;
while(rs.next()) {
rowCount++;
BasicTrainScheduleEntry btse = new BasicTrainScheduleEntry();
btse.setSuid(rs.getString(1));
btse.setTrainUid(rs.getString(2));
btse.setScheduleType(ScheduleType.valueOf(rs.getString(3)));
btse.setSignalId(rs.getString(4));
btse.setToc(rs.getString(5));
btse.setTrainClass(rs.getString(6));
btse.setOrigin(rs.getString(7));
btse.setOriginTime(rs.getLong(8));
btse.setDestination(rs.getString(9));
btse.setDestinationTime(rs.getLong(10));
btse.setDepartTime(rs.getLong(11));
btse.setDepartPlatform(rs.getString(12));
btse.setArriveTime(rs.getLong(13));
btse.setArrivePlatform(rs.getString(14));
trains.add(btse);
tocList.add(btse.getToc());
tcList.add(btse.getTrainClass());
locList.add(btse.getOrigin());
locList.add(btse.getDestination());
if(!trainGroups.containsKey(btse.getTrainUid())) {
trainGroups.put(btse.getTrainUid(), new TrainScheduleEntry());
}
trainGroups.get(btse.getTrainUid()).addEntry(btse);
}
log.atInfo().log("{} train schedule found.", rowCount);
log.atInfo().log("{} train group formed.", trainGroups.size());
}
}catch(SQLException e) {
log.atError().log(e.getMessage(), e);
}
for(TrainScheduleEntry tse:trainGroups.values()) {
trainGroup.add(tse);
}
//Scan for earlier train arrives later
for(TrainScheduleEntry tse:trainGroup) {
for(TrainScheduleEntry otse:trainGroup) {
if(tse.getTrainUid().equals(otse.getTrainUid())) {
continue;//No need to check with self
}
if(tse.getDepartTime() <= otse.getDepartTime() && tse.getArriveTime() >= otse.getArriveTime() && otse.getArriveTime() > otse.getDepartTime()) {
tse.setNote("A");
break;
}
}
}
try(
Connection conn = DatabaseManager.getInstance().getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT tps_desc FROM tiploc WHERE crs = ?");
){
for(String crs:locList) {
stmt.setString(1, crs);
try(ResultSet rs = stmt.executeQuery()){
if(rs.next()) {
locCache.put(crs, rs.getString(1));
}
}
}
}catch(SQLException e) {
log.atError().log(e.getMessage(), e);
}
//Generate output
try(PrintWriter pw = new PrintWriter(new File("Z:\\output.tex"))){
pw.print(LATEX_PREMBLE_1);
pw.println("\\begin{document}");
pw.println("\\begin{center}\\begin{LARGE}");
pw.println("Train running record from \\\\"+locCache.get(origin)+"\\\\to\\\\"+locCache.get(destination)+"\\\\on\\\\"+new java.text.SimpleDateFormat("dd-MM-yyyy").format(rptDate));
pw.println("\\end{LARGE}\\end{center}");
pw.println();
pw.println("\\hr\r\n" +
" \r\n" +
" The information in this report is generated from data feed provided by Network Rail Infrastructure Limited.\r\n" +
" \r\n" +
" \\hr\r\n" +
" \\tableofcontents");
//Part 1: Definations
pw.println("\\section{Definations}");
pw.println("\\subsection{TOC}");
try(
Connection conn = DatabaseManager.getInstance().getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT name FROM toc WHERE atoc_code = ? LIMIT 1");
){
int count = 0;
for(String toc:tocList) {
stmt.setString(1, toc);
try(ResultSet rs = stmt.executeQuery()){
if(rs.next()) {
pw.print(rs.getString(1));
if(++count%2==0)
pw.print("\\dfa ");
else
pw.print("\\dfb ");
pw.print(toc);
pw.println("\\\\");
tocCache.put(toc, rs.getString(1));
}
}
}
}catch(SQLException e) {
log.atError().log(e.getMessage(), e);
}
pw.println("\\subsection{Train Class}");
try(
Connection conn = DatabaseManager.getInstance().getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT category_name FROM train_category WHERE category = ? LIMIT 1");
){
int count = 0;
for(String tc:tcList) {
stmt.setString(1, tc);
try(ResultSet rs = stmt.executeQuery()){
if(rs.next()) {
pw.print(rs.getString(1));
if(++count%2==0)
pw.print("\\dfa ");
else
pw.print("\\dfb ");
pw.print(tc);
pw.println("\\\\");
tcCache.put(tc, rs.getString(1));
}
}
}
}catch(SQLException e) {
log.atError().log(e.getMessage(), e);
}
pw.println("\\subsection{Location}");
int locCount = 0;
for(String loc:locList) {
pw.print(locCache.get(loc).replace("&", "\\&"));
if(++locCount%2==0)
pw.print("\\dfa ");
else
pw.print("\\dfb ");
pw.print(loc);
pw.print("\\\\");
}
//Part 2: Print the train List
pw.println("\\section{Train Schedule}");
pw.println("\\begin{longtable}[l]{|c|c|c||cc|cc|cc|cc||c|c|}");
pw.println("\\hline\r\n" +
" UID & TOC & Train class & "
+ "\\multicolumn{2}{c|}{Origin}& \\multicolumn{2}{c|}{"+origin+"} & "
+ "\\multicolumn{2}{c|}{"+destination+"} &\\multicolumn{2}{c||}{Destination} & Detail Page &Note\\\\\\hline\\endhead");
int recCount = 0;
TrainScheduleEntry ltse = null;
for(TrainScheduleEntry tse:trainGroup) {
if(ltse!=null) {
if(getHour(ltse.getDepartTime())!=getHour(tse.getDepartTime())) {
pw.println("\\\\\\hline");
}else {
pw.println("\\\\");
}
}
if(tse.getSubentryCount()==1) {
//Basic layout
pw.print(tse.getSignalId());
pw.print("&");
pw.print(tse.getToc());
pw.print("&");
pw.print(tse.getTrainClass());
pw.print("&");
pw.print(tse.getOrigin());
pw.print("&");
pw.print(getTime(tse.getOriginTime()));
pw.print("&");
pw.print(getTime(tse.getDepartTime()));
pw.print("&\\small{");
pw.print(tse.getDepartPlatform());
pw.print("}&");
pw.print(getTime(tse.getArriveTime()));
pw.print("&\\small{");
pw.print(tse.getArrivePlatform());
pw.print("}&");
pw.print(tse.getDestination());
pw.print("&");
pw.print(getTime(tse.getDestinationTime()));
pw.print("&\\pageref{td:");
pw.print(tse.getTrainUid());
pw.print("}&");
pw.print(tse.getNote());
if(tse.getScheduleType()==ScheduleType.CAN)
pw.print("C");
}else {
//Advance layout
recCount++;
BasicTrainScheduleEntry assoc = tse.getAssocEntry();
boolean hasChange = false;
//Print main record
if(recCount%2==0)
pw.print("\\rowcolor{hl1}");
else
pw.print("\\rowcolor{hl2}");
if(!tse.getSignalId().equals(assoc.getSignalId())) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(tse.getSignalId());
if(!tse.getSignalId().equals(assoc.getSignalId())) {
pw.print("}");
}
pw.print("&");
if(!tse.getToc().equals(assoc.getToc())) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(tse.getToc());
if(!tse.getToc().equals(assoc.getToc())) {
pw.print("}");
}
pw.print("&");
if(!tse.getTrainClass().equals(assoc.getTrainClass())) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(tse.getTrainClass());
if(!tse.getTrainClass().equals(assoc.getTrainClass())) {
pw.print("}");
}
pw.print("&");
if(!tse.getOrigin().equals(assoc.getOrigin())) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(tse.getOrigin());
if(!tse.getOrigin().equals(assoc.getOrigin())) {
pw.print("}");
}
pw.print("&");
if(tse.getOriginTime()!=assoc.getOriginTime()) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(getTime(tse.getOriginTime()));
if(tse.getOriginTime()!=assoc.getOriginTime()) {
pw.print("}");
}
pw.print("&");
if(tse.getDepartTime()!=assoc.getDepartTime()) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(getTime(tse.getDepartTime()));
if(tse.getDepartTime()!=assoc.getDepartTime()) {
pw.print("}");
}
pw.print("&");
if(!tse.getDepartPlatform().equals(assoc.getDepartPlatform())) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print("\\small{");
pw.print(tse.getDepartPlatform());
pw.print("}");
if(!tse.getDepartPlatform().equals(assoc.getDepartPlatform())) {
pw.print("}");
}
pw.print("&");
if(tse.getArriveTime()!=assoc.getArriveTime()) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(getTime(tse.getArriveTime()));
if(tse.getArriveTime()!=assoc.getArriveTime()) {
pw.print("}");
}
pw.print("&");
if(!tse.getArrivePlatform().equals(assoc.getArrivePlatform())) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print("\\small{");
pw.print(tse.getArrivePlatform());
pw.print("}");
if(!tse.getArrivePlatform().equals(assoc.getArrivePlatform())) {
pw.print("}");
}
pw.print("&");
if(!tse.getDestination().equals(assoc.getDestination())) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(tse.getDestination());
if(!tse.getDestination().equals(assoc.getDestination())) {
pw.print("}");
}
pw.print("&");
if(tse.getDestinationTime()!=assoc.getDestinationTime()) {
hasChange = true;
pw.print("\\textcolor{red}{");
}
pw.print(getTime(tse.getDestinationTime()));
if(tse.getDestinationTime()!=assoc.getDestinationTime()) {
pw.print("}");
}
pw.print("&\\pageref{td:");
pw.print(tse.getTrainUid());
pw.print("}&");
pw.print(tse.getNote());
pw.print("B");
if(tse.getScheduleType()==ScheduleType.CAN)
pw.print("C");
if(hasChange) {
pw.print("\\\\*");
//Print ORIGINAL record
if(recCount%2==0)
pw.print("\\rowcolor{hl1}");
else
pw.print("\\rowcolor{hl2}");
if(!tse.getSignalId().equals(assoc.getSignalId())) {
hasChange = true;
pw.print("\\sout{");
pw.print(assoc.getSignalId());
pw.print("}");
}
pw.print("&");
if(!tse.getToc().equals(assoc.getToc())) {
hasChange = true;
pw.print("\\sout{");
pw.print(assoc.getToc());
pw.print("}");
}
pw.print("&");
if(!tse.getTrainClass().equals(assoc.getTrainClass())) {
hasChange = true;
pw.print("\\sout{");
pw.print(assoc.getTrainClass());
pw.print("}");
}
pw.print("&");
if(!tse.getOrigin().equals(assoc.getOrigin())) {
hasChange = true;
pw.print("\\sout{");
pw.print(assoc.getOrigin());
pw.print("}");
}
pw.print("&");
if(tse.getOriginTime()!=assoc.getOriginTime()) {
hasChange = true;
pw.print("\\sout{");
pw.print(getTime(assoc.getOriginTime()));
pw.print("}");
}
pw.print("&");
if(tse.getDepartTime()!=assoc.getDepartTime()) {
hasChange = true;
pw.print("\\sout{");
pw.print(getTime(assoc.getDepartTime()));
pw.print("}");
}
pw.print("&");
if(!tse.getDepartPlatform().equals(assoc.getDepartPlatform())) {
hasChange = true;
pw.print("\\sout{");
pw.print("\\small{");
pw.print(assoc.getDepartPlatform());
pw.print("}");
pw.print("}");
}
pw.print("&");
if(tse.getArriveTime()!=assoc.getArriveTime()) {
hasChange = true;
pw.print("\\sout{");
pw.print(getTime(assoc.getArriveTime()));
pw.print("}");
}
pw.print("&");
if(!tse.getArrivePlatform().equals(assoc.getArrivePlatform())) {
hasChange = true;
pw.print("\\sout{");
pw.print("\\small{");
pw.print(assoc.getArrivePlatform());
pw.print("}");
pw.print("}");
}
pw.print("&");
if(!tse.getDestination().equals(assoc.getDestination())) {
hasChange = true;
pw.print("\\sout{");
pw.print(assoc.getDestination());
pw.print("}");
}
pw.print("&");
if(tse.getDestinationTime()!=assoc.getDestinationTime()) {
hasChange = true;
pw.print("\\sout{");
pw.print(getTime(assoc.getDestinationTime()));
pw.print("}");
}
pw.print("&&");
}
}
ltse = tse;
}
pw.println("\\\\\\hline\\end{longtable}");
pw.println("Note:\\\\");
pw.println("A\\dfa Faster train available\\\\");
pw.println("B\\dfb Changes to timetable applies\\\\");
pw.println("C\\dfa Scheduled cancellation\\\\");
pw.println("\\pageref{xx:ukn}\\dfb No train details found\\\\");
//Details
pw.println("\\section{Schedule Details}");
for(TrainScheduleEntry tse:trainGroup) {
TrainRunningRecord trr = getRunningRecord(tse.getMainSUID(), rptDate);
if(trr==null) {
log.atWarn().log("No record for {}", tse.getMainSUID());
continue;
}
pw.println("\\subsection{"+tse.getSignalId()+" "+getTime(tse.getOriginTime())+" to "+locCache.get(tse.getDestination()).replace("&", "\\&")+"}\\label{td:"+tse.getTrainUid()+"}");
pw.println();
pw.println("Basic infomation\\\\");
pw.println("From "+locCache.get(tse.getOrigin()).replace("&", "\\&")+" to "+locCache.get(tse.getDestination()).replace("&", "\\&")+"\\\\");
pw.println("Operated by "+tocCache.get(tse.getToc())+"\\\\");
pw.println(tcCache.get(tse.getTrainClass())+"\\\\");
pw.println("Train UID: "+tse.getTrainUid()+"\\\\");
try(
Connection conn = DatabaseManager.getInstance().getConnection();
PreparedStatement pstmt = conn.prepareStatement("SELECT power_type, planned_speed, class, sleeper, reservation, catering, atoc_code, rsid FROM ltp_schedule WHERE suid = ?")
){
pstmt.setString(1, tse.getMainSUID());
try(ResultSet rs = pstmt.executeQuery()){
if(rs.next()) {
pw.println("Train ID: "+trr.getTrainId()+"\\\\");
pw.println("Activated on: "+new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date(trr.getActivate()))+"\\\\");
pw.println("Power type: "+rs.getString(1)+"\\\\");
pw.println("Planned speed "+rs.getString(2)+"mph\\\\");
if("".equals(rs.getString(3))||"B".equals(rs.getString(3))) {
pw.println("First class available\\\\");
}else {
pw.println("Only ordinary class available\\\\");
}
if(rs.getString(8)!=null) {
pw.println("National Reservation System headcode : "+rs.getString(7)+rs.getString(8));
}
}
}
}catch(SQLException e) {
log.atError().log(e.getMessage(), e);
}
pw.println();
pw.println("\\begin{longtable}[l]{|p{5.5cm}r|ccc|ccc|lr|}");
pw.println("\\hline\r\n" +
" \\multicolumn{2}{|c|}{Station} & \\multicolumn{3}{c|}{Arrival}& \\multicolumn{3}{c|}{Departure}&\r\n" +
" Plat. & Diff.\\\\\r\n" +
" & & GBTT & WTT & Actual & GBTT & WTT & Actual & &\\\\\\hline\\endhead");
for(TrainRunningRecordEntry trre:trr.getEntries()) {
if(trre.getLocationName()==null)
continue;
boolean pass = false;
if(origin.equals(trre.getCrs()))
pw.print("\\rowcolor{hl1}");
if(destination.equals(trre.getCrs()))
pw.print("\\rowcolor{hl2}");
pw.print(trre.getLocationName().replace("&", "\\&"));
pw.print("&");
if(trre.getCrs()!=null)
pw.print(trre.getCrs());
pw.print("&");
//ARRIVAL
if(trre.getAgbtt()!=0)
pw.print(getTime(trre.getAgbtt()));
pw.print("&");
if(trre.getAwtt()!=0)
pw.print(getTime(trre.getAwtt()));
pw.print("&");
if(trre.getAact()!=0)
pw.print(getTime(trre.getAact()));
pw.print("&");
//ARRIVAL
if(trre.getDgbtt()!=0)
pw.print(getTime(trre.getDgbtt()));
else if(trre.getDwtt()!=0) {
pw.print("\\pa");
pass = true;
}
pw.print("&");
if(trre.getDwtt()!=0)
pw.print(getTime(trre.getDwtt()));
pw.print("&");
if(trre.getDact()!=0)
pw.print(getTime(trre.getDact()));
pw.print("&");
if(trre.getPlatform()!=null)
pw.print(trre.getPlatform());
pw.print("&");
long sch, act;
if(pass||(trre.getAgbtt()==0&&trre.getAwtt()==0&&trre.getAact()==0)) {
sch = trre.getDgbtt()!=0?trre.getDgbtt():trre.getDwtt();
act = trre.getDact();
}else {
sch = trre.getAgbtt()!=0?trre.getAgbtt():trre.getAwtt();
act = trre.getAact();
}
if(sch!=0 && !tse.getOrigin().equals(trre.getCrs())) {
int diffMin = (int)(act-sch)/60;
if(diffMin < -240) diffMin+=1440;
if(diffMin < 0) pw.print("\\textcolor{e1}{");
else if(diffMin > 30) pw.print("\\textcolor{l3}{");
else if(diffMin > 15) pw.print("\\textcolor{l2}{");
else if(diffMin > 0) pw.print("\\textcolor{l1}{");
else pw.print("\\textcolor{ot}{");
pw.print(diffMin);
pw.print("}");
}
pw.println("\\\\");
}
pw.println("\\hline\\end{longtable}");
pw.println();
}
pw.println("This is the end of the report");
pw.println("\\end{document}");
}
return null;
}
private static TrainRunningRecord getRunningRecord(String suid, java.util.Date opDate) {
TrainRunningRecord trr = new TrainRunningRecord();
try(Connection conn = DatabaseManager.getInstance().getConnection()){
//Step 1: Find the activation record
try(PreparedStatement stmt = conn.prepareStatement("SELECT train_id, activate_time FROM current_train WHERE suid=? AND op_date=?")){
stmt.setString(1, suid);
stmt.setDate(2, new java.sql.Date(opDate.getTime()));
try(ResultSet rs = stmt.executeQuery()){
if(rs.next()) {
trr.setTrainId(rs.getString(1));
trr.setActivate(rs.getTimestamp(2).getTime());
}else {
return null;
}
}
}
//Step 2: get the actual record
try(PreparedStatement stmt = conn.prepareStatement("SELECT get_stanox_name(loc_stanox) loc, stanox_to_crs(loc_stanox) crs,\r\n" +
" TIME_TO_SEC(gbtt_time) ttt, TIME_TO_SEC(plan_time) plt, TIME_TO_SEC(movt_time) act,\r\n" +
" platform plat, CASE evnt_type WHEN 'DEPARTURE' THEN 'D' WHEN 'ARRIVAL' THEN 'A' ELSE '?' END, loc_stanox t\r\n" +
" FROM current_train_movement WHERE train_id = ? ORDER BY movt_time, evnt_type;")){
stmt.setString(1, trr.getTrainId());
try(ResultSet rs = stmt.executeQuery()){
TrainRunningRecordEntry trre = new TrainRunningRecordEntry();
while(rs.next()) {
if(!rs.getString(8).equals(trre.getStanox())) {
//Changed
trr.getEntries().add(trre);
trre = new TrainRunningRecordEntry();
}
trre.setCrs(rs.getString(2));
String locName = rs.getString(1);
if(locName.length()>20) {
locName=locName
.replace("JUNCTION", "JN")
.replace("INTERNATIONAL", "INTL")
.replace("THAMESLINK", "TL");
}
trre.setLocationName(locName);
trre.setPlatform(rs.getString(6));
trre.setStanox(rs.getString(8));
if("A".equals(rs.getString(7))) {
//Arrival
trre.setAgbtt(rs.getLong(3));
trre.setAwtt(rs.getLong(4));
trre.setAact(rs.getLong(5));
}else {
//Departure
trre.setDgbtt(rs.getLong(3));
trre.setDwtt(rs.getLong(4));
trre.setDact(rs.getLong(5));
}
}
trr.getEntries().add(trre);
}
}
}catch(SQLException e) {
log.atError().log(e.getMessage(), e);
}
return trr;
}
private static String getTime(long sec) {
long h = sec/3600;
long m = (sec/60)%60;
StringBuilder sb = new StringBuilder();
if(h<10) sb.append("0");
sb.append(h).append(":");
if(m<10) sb.append("0");
sb.append(m);
return sb.toString();
}
private static int getHour(long sec) {
return (int) sec/3600;
}
}

35
src/org/leolo/rail/report/TrainRunningRecord.java

@ -0,0 +1,35 @@
package org.leolo.rail.report;
import java.util.ArrayList;
import java.util.Vector;
public class TrainRunningRecord {
private String trainId;
private long activate;
private Vector<TrainRunningRecordEntry> entries = new Vector<>();
public String getTrainId() {
return trainId;
}
public Vector<TrainRunningRecordEntry> getEntries() {
return entries;
}
public void setTrainId(String trainId) {
this.trainId = trainId;
}
public long getActivate() {
return activate;
}
public void setActivate(long activate) {
this.activate = activate;
}
}

76
src/org/leolo/rail/report/TrainRunningRecordEntry.java

@ -0,0 +1,76 @@
package org.leolo.rail.report;
public class TrainRunningRecordEntry {
private String locationName;
private String crs;
private String stanox;
private String platform;
private long agbtt;
private long awtt;
private long aact;
private long dgbtt;
private long dwtt;
private long dact;
public String getLocationName() {
return locationName;
}
public String getCrs() {
return crs;
}
public long getAgbtt() {
return agbtt;
}
public long getAwtt() {
return awtt;
}
public long getAact() {
return aact;
}
public long getDgbtt() {
return dgbtt;
}
public long getDwtt() {
return dwtt;
}
public long getDact() {
return dact;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public void setCrs(String crs) {
this.crs = crs;
}
public void setAgbtt(long agbtt) {
this.agbtt = agbtt;
}
public void setAwtt(long awtt) {
this.awtt = awtt;
}
public void setAact(long aact) {
this.aact = aact;
}
public void setDgbtt(long dgbtt) {
this.dgbtt = dgbtt;
}
public void setDwtt(long dwtt) {
this.dwtt = dwtt;
}
public void setDact(long dact) {
this.dact = dact;
}
public String getPlatform() {
return platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public String getStanox() {
return stanox;
}
public void setStanox(String stanox) {
this.stanox = stanox;
}
}

105
src/org/leolo/rail/report/TrainScheduleEntry.java

@ -0,0 +1,105 @@
package org.leolo.rail.report;
import java.util.HashSet;
import org.leolo.rail.model.ScheduleType;
public class TrainScheduleEntry {
private HashSet<BasicTrainScheduleEntry> subEntry = new HashSet<>();
private BasicTrainScheduleEntry mainEntry = null;
private String note = "";
public void addEntry(BasicTrainScheduleEntry entry) {
subEntry.add(entry);
if(mainEntry==null) {
mainEntry = entry;
}else if(entry.getScheduleType() == ScheduleType.OVL) {
mainEntry = entry;
}
}
public int getSubentryCount() {
return subEntry.size();
}
public BasicTrainScheduleEntry getAssocEntry() {
for(BasicTrainScheduleEntry btse:subEntry) {
if(btse!=mainEntry) {
return btse;
}
}
return null;
}
public String getMainSUID() {
return mainEntry.getSuid();
}
public ScheduleType getScheduleType() {
return mainEntry.getScheduleType();
}
public String getSignalId() {
return mainEntry.getSignalId();
}
public String getToc() {
return mainEntry.getToc();
}
public String getTrainClass() {
return mainEntry.getTrainClass();
}
public String getOrigin() {
return mainEntry.getOrigin();
}
public long getOriginTime() {
return mainEntry.getOriginTime();
}
public String getDestination() {
return mainEntry.getDestination();
}
public long getDestinationTime() {
return mainEntry.getDestinationTime();
}
public HashSet<BasicTrainScheduleEntry> getAssoicatedEntry() {
return mainEntry.getAssoicatedEntry();
}
public String getTrainUid() {
return mainEntry.getTrainUid();
}
public long getDepartTime() {
return mainEntry.getDepartTime();
}
public String getDepartPlatform() {
return mainEntry.getDepartPlatform();
}
public long getArriveTime() {
return mainEntry.getArriveTime();
}
public String getArrivePlatform() {
return mainEntry.getArrivePlatform();
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
Loading…
Cancel
Save