Skip to content

Instantly share code, notes, and snippets.

@skht777
Last active May 1, 2018 17:07
Show Gist options
  • Select an option

  • Save skht777/c87aa81063a0052d656745777f41450e to your computer and use it in GitHub Desktop.

Select an option

Save skht777/c87aa81063a0052d656745777f41450e to your computer and use it in GitHub Desktop.
KancolleSchedulerOnline
import * as d3 from 'd3';
/**
* 遠征情報を表すクラス
*/
class Expedition {
/**
* 遠征海域名
*/
private _areaName: string;
get areaName(): string { return this._areaName; }
/**
* 遠征名
*/
private _name: string;
get name(): string { return this._name; }
/**
* 遠征時間
*/
private _time: number;
get time(): number { return this._time; }
/**
* 色ID(配列)
*/
private _color: number[];
get color(): number[] { return this._color; }
/**
* コンストラクタ
* @param area_name 遠征海域名
* @param name 遠征名
* @param time 遠征時間
* @param color1 色1
* @param color2 色2
*/
constructor(areaName: string, name: string, time: number, color1: number, color2: number) {
this._areaName = areaName;
this._name = name;
this._time = time;
this._color = [color1, color2];
}
};
/**
* 遠征タスクを表すクラス
*/
class ExpeditionTask {
/**
* 遠征情報
*/
private _expedition: Expedition;
get expedition(): Expedition { return this._expedition; }
/**
* 遠征が始まるタイミングを分単位で指定
*/
private _timing: number;
get timing(): number { return this._timing; }
/**
* 第n艦隊なのか(艦隊番号)を指定
*/
private _fleetIndex: number;
get fleetIndex(): number { return this._fleetIndex; }
/**
* 枠のx座標
*/
rx: number;
/**
* 枠のy座標
*/
ry: number;
/**
* 遠征名のx座標
*/
tx: number;
/**
* 遠征名のy座標
*/
ty: number;
/**
* コンストラクタ
* @param expedition 遠征情報
* @param timing 遠征が始まるタイミング
* @param fleetIndex 艦隊番号
*/
constructor(expedition: Expedition, timing: number, fleetIndex: number) {
this._expedition = expedition;
this._timing = timing;
this._fleetIndex = fleetIndex;
this.rx = Constant.TASK_WIDTH * fleetIndex + Constant.CANVAS_HOUR_MARGIN;
this.ry = Constant.TASK_HEIGHT_PER_TIME * timing;
this.tx = this.rx;
this.ty = this.ry + 18 + 2;
}
};
/**
* 遠征情報および遠征タスク情報を格納するデータベース
*/
class DataStore {
/**
* 遠征一覧
*/
private static expeditionList: Array<Expedition>;
/**
* データベースを初期化
*/
static initialize() {
DataStore.expeditionList = new Array<Expedition>();
DataStore.expeditionList.push(new Expedition("鎮守府海域", "長距離練習航海", 30, 1, 4));
DataStore.expeditionList.push(new Expedition("鎮守府海域", "海上護衛任務", 90, 0, 1));
DataStore.expeditionList.push(new Expedition("鎮守府海域", "防空射撃演習", 40, 3, 3));
DataStore.expeditionList.push(new Expedition("鎮守府海域", "長時間対潜警戒", 135, 0, 4));
DataStore.expeditionList.push(new Expedition("鎮守府海域", "強行偵察任務", 90, 1, 4));
DataStore.expeditionList.push(new Expedition("鎮守府海域", "鼠輸送作戦", 240, 0, 1));
}
/**
* 遠征名・タイミング・艦隊番号から遠征タスクを作成
* @param name 遠征名
* @param timing タイミング
* @param fleetIndex 艦隊番号
*/
static makeExpeditionTask(name: String, timing: number, fleetIndex: number): ExpeditionTask {
let expedition = DataStore.expeditionList.filter(e => e.name == name)[0];
return new ExpeditionTask(expedition, timing, fleetIndex);
}
};
class Constant{
/**
* 遠征タスクの横幅
*/
static TASK_WIDTH: number = 150;
/**
* 遠征タスクの縦幅(/分)
*/
static TASK_HEIGHT_PER_TIME: number = 1;
/**
* 遠征の総艦隊数
*/
static FLEET_COUNT: number = 3;
/**
* 1日の時間数
*/
static HOURS: number = 24;
/**
* 1時間の分数
*/
static MINUTES: number = 60;
/**
* 1日の分数
*/
static ALL_TIMES: number = Constant.MINUTES * Constant.HOURS;
/**
* 時間を表示するための余白
*/
static CANVAS_HOUR_MARGIN: number = 50;
/**
* スケジュール表示の横幅
*/
static CANVAS_WIDTH: number = Constant.TASK_WIDTH * Constant.FLEET_COUNT + Constant.CANVAS_HOUR_MARGIN;
/**
* スケジュール表示の縦幅
*/
static CANVAS_HEIGHT: number = Constant.TASK_HEIGHT_PER_TIME * Constant.ALL_TIMES;
};
class MainController {
/**
* 遠征タスクの一覧
*/
private expTaskList: Array<ExpeditionTask> = new Array<ExpeditionTask>();
/**
* 遠征スケジュールを描画するための盤面
* 型推論させるため、意図的にここで代入している
*/
private canvas = d3.select("#canvas").append("svg")
.attr("width", Constant.CANVAS_WIDTH)
.attr("height", Constant.CANVAS_HEIGHT);
/**
* 遠征タスクを初期化
*/
private initializeCanvas(){
let line = function (selection, x1, x2, y1, y2) {
return selection.attr("x1", x1)
.attr("x2", x2)
.attr("y1", y1)
.attr("y2", y2)
.attr("stroke-width", 1)
.attr("stroke", "black");
};
let lineY = (s, x, y1, y2) => line(s, x, x, y1, y2);
let lineX = (s, x1, x2, y) => line(s, x1, x2, y, y);
// 縦方向の罫線
// (太さ1の黒い実線)
this.canvas.selectAll("v-line")
.data(d3.range(Constant.FLEET_COUNT + 1))
.enter().append("line")
.classed("v-line", true)
.call(lineY,
w => Constant.TASK_WIDTH * w + Constant.CANVAS_HOUR_MARGIN, // x
0, // y1
Constant.CANVAS_HEIGHT // y2
);
// 横方向の罫線と時刻表示
// (太さ1の黒い実線、文字は18pxで遠征スケジュールの左側に表示)
this.canvas.selectAll("h-line")
.data(d3.range(Constant.HOURS + 1))
.enter().append("line")
.classed("h-line", true)
.call(lineX,
0 + Constant.CANVAS_HOUR_MARGIN, // x1
Constant.CANVAS_WIDTH + Constant.CANVAS_HOUR_MARGIN, // x2
h => Constant.TASK_HEIGHT_PER_TIME * Constant.MINUTES * h // y
);
let hourString = h => ((h + 5) % Constant.HOURS).toString() + ":00";
this.canvas.selectAll("hour")
.data(d3.range(Constant.HOURS + 1))
.enter().append("text")
.classed("hour", true)
.attr("x", h => Constant.CANVAS_HOUR_MARGIN - hourString(h).length * 18 / 2)
.attr("y", h => Constant.TASK_HEIGHT_PER_TIME * Constant.MINUTES * h + (h == 0 ? 18 : h == Constant.HOURS ? 0 : 9))
.attr("font-size", "18px")
.text(h => hourString(h));
}
/**
* 遠征スケジュールを再描画する
*/
redrawCanvas(){
/**
* ドラッグスタート時に呼び出される関数
*/
let dragstartedTask = function () {
};
/**
* ドラッグ中に呼び出される関数
*/
let draggedTask = function () {
d3.select(this).selectAll(".movable")
.attr("x", function (d) { return parseFloat(d3.select(this).attr("x")) + d3.event.dx })
.attr("y", function (d) { return parseFloat(d3.select(this).attr("y")) + d3.event.dy });
}
/**
* ドラッグ終了時に呼び出される関数
*/
let dragendedTask = function () {
}
// 遠征タスクをまとめて消去
this.canvas.selectAll("g").remove();
// 遠征タスクをまとめて描画するための下地
let tasks = this.canvas.selectAll("g")
.data<ExpeditionTask>(this.expTaskList)
.enter()
.append("g")
.call(
d3.drag<SVGElement, ExpeditionTask>()
.on("start", dragstartedTask)
.on("drag", draggedTask)
.on("end", dragendedTask)
);
// 遠征タスクをまとめて描画
// (枠の色は透明度0%の黒、内部塗りつぶしは透明度20%のskyblue)
tasks.append("rect")
.classed("movable", true)
.attr("x", function(task) { return task.rx; })
.attr("y", function(task) { return task.ry; })
.attr("width",Constant.TASK_WIDTH)
.attr("height", function(task){
return Constant.TASK_HEIGHT_PER_TIME * task.expedition.time;
})
.attr("stroke", "black")
.style("opacity", 0.8)
.attr("fill","skyblue");
// (文字は18pxで、遠征タスク枠の左上に横向きで描画)
tasks.append("text")
.classed("movable", true)
.attr("x", function(task) { return task.tx; })
.attr("y", function(task) { return task.ty; })
.attr("font-size", "18px")
.text(function(task){
return task.expedition.name;
});
}
test(){
this.expTaskList.length = 0;
this.expTaskList.push(DataStore.makeExpeditionTask("海上護衛任務",0,2));
this.expTaskList.push(DataStore.makeExpeditionTask("長時間対潜警戒",100,1));
this.expTaskList.push(DataStore.makeExpeditionTask("鼠輸送作戦",200,0));
}
/**
* コンストラクタ
*/
constructor(){
// expTaskListを初期化
this.expTaskList.push(DataStore.makeExpeditionTask("長時間対潜警戒",95,0));
this.expTaskList.push(DataStore.makeExpeditionTask("強行偵察任務",95,1));
this.expTaskList.push(DataStore.makeExpeditionTask("鼠輸送作戦",95,2));
this.expTaskList.push(DataStore.makeExpeditionTask("長時間対潜警戒",230,0));
this.expTaskList.push(DataStore.makeExpeditionTask("強行偵察任務",185,1));
this.expTaskList.push(DataStore.makeExpeditionTask("長時間対潜警戒",425,0));
this.expTaskList.push(DataStore.makeExpeditionTask("長時間対潜警戒",815,0));
this.expTaskList.push(DataStore.makeExpeditionTask("長時間対潜警戒",950,0));
this.expTaskList.push(DataStore.makeExpeditionTask("強行偵察任務",425,1));
this.expTaskList.push(DataStore.makeExpeditionTask("強行偵察任務",815,1));
this.expTaskList.push(DataStore.makeExpeditionTask("強行偵察任務",905,1));
this.expTaskList.push(DataStore.makeExpeditionTask("強行偵察任務",995,1));
this.expTaskList.push(DataStore.makeExpeditionTask("鼠輸送作戦",425,2));
this.expTaskList.push(DataStore.makeExpeditionTask("鼠輸送作戦",815,2));
// canvasを初期化
this.initializeCanvas();
}
};
/**
* スタートアップ
*/
window.onload = () => {
let element = document.getElementById("taskList");
// データベースを初期化
DataStore.initialize();
// Controllerを初期化
let mc = new MainController();
// 画面を再描画
mc.redrawCanvas();
mc.test();
mc.redrawCanvas();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment