Преглед изворни кода

Merge pull request #1 from Razenpok/main

Add Treemap charts for Company Totals
SamuelBurnes пре 10 месеци
родитељ
комит
3f6c8be07e
3 измењених фајлова са 544 додато и 5 уклоњено
  1. 2 1
      index.html
  2. 71 4
      main.js
  3. 471 0
      material-info.js

+ 2 - 1
index.html

@@ -6,6 +6,7 @@
     <title>PrUn Financial Reports</title>
 	<link rel="stylesheet" href="styles.css">
 	<link rel="icon" type="image/x-icon" href="icon128.png">
+	<script src="material-info.js"></script>
 	<script src="main.js"></script>
 	<script src="https://cdn.plot.ly/plotly-3.0.1.min.js" charset="utf-8"></script>
 </head>
@@ -46,4 +47,4 @@
 </div>
 
 </body>
-</html>
+</html>

+ 71 - 4
main.js

@@ -39,7 +39,7 @@ function updateSelectors(graphTypeSelector, selectorSubtypes)
 	}
 	else if(graphTypeSelector.value == "compTotals")
 	{
-		const chartTypeElem = addInput('select', 'chartType', 'Chart Type: ', [['Pie', 'Bar'], ['pie', 'bar']]);
+		const chartTypeElem = addInput('select', 'chartType', 'Chart Type: ', [['Treemap', 'Treemap (categories)', 'Pie', 'Bar'], ['treemap', 'treemap-categories', 'pie', 'bar']]);
 		chartTypeElem.style.marginLeft = "-30px";
 		selectorSubtypes.appendChild(chartTypeElem);
 		
@@ -524,8 +524,75 @@ function generateCompanyGraph(container, chartType, data, companyName, month, me
 	var indices = values.map((_, i) => i).sort((a, b) => values[b] - values[a]);
 	mats = indices.map(i => mats[i]);
 	values = indices.map(i => values[i]);
-	
-	if(chartType == 'pie')
+
+	if(chartType == 'treemap' || chartType == 'treemap-categories')
+	{
+		// Filter out negative values
+		indices = values
+			.map((v, i) => i)
+			.filter(i => values[i] >= 0);
+		mats = indices.map(i => mats[i]);
+		values = indices.map(i => values[i]);
+
+		var colors = mats.map(m => materialsToColors[m] || '#000000');
+		var parents = chartType == 'treemap-categories'
+			? mats.map(m => materialsToCategories[m] || 'Other')
+			: mats.map(m => 'Total');
+
+		var totalValue = 0;
+		var categoryValues = {};
+		for (const i of indices) {
+			totalValue += values[i];
+			const category = parents[i];
+			categoryValues[category] = (categoryValues[category] || 0) + values[i];
+		}
+
+		if (chartType == 'treemap-categories') {
+			for (const category in categoryValues) {
+				mats.push(category);
+				values.push(categoryValues[category]);
+				colors.push(materialCategoryColors[category] || '#000000');
+				parents.push('Total');
+			}
+		}
+
+		values.push(totalValue);
+		mats.push('Total');
+		parents.push('');
+		colors.push('#252525');
+
+		Plotly.newPlot(container, {
+			data: [
+				{
+					type: 'treemap',
+					labels: mats,
+					parents: parents,
+					values: values,
+					maxdepth: 2,
+					branchvalues: 'total',
+					marker: {
+						colors: colors,
+					},
+					tiling: {
+						pad: 0,
+					},
+					textposition: 'middle center',
+					hovertemplate: '%{label}<br>$%{value:,.3~s}/day<br>%{percentEntry:.2%}<extra></extra>'
+				}
+			],
+			layout: { width: 800, height: 600,
+				title: {text: titles[metric] + companyName + ' - ' + prettyMonthName(month),
+					font: {color: '#eee', family: '"Droid Sans", sans-serif'},
+				},
+				plot_bgcolor: '#252525',
+				paper_bgcolor: '#252525',
+			},
+			config: {
+				displaylogo: false,
+			}
+		});
+	}
+	else if(chartType == 'pie')
 	{
 		// Filter out negative values
 		indices = values
@@ -841,4 +908,4 @@ const prettyModeNames = {
 	"profit": "Profit",
 	"volume": "Volume",
 	"price": "Price"
-}
+}

+ 471 - 0
material-info.js

@@ -0,0 +1,471 @@
+var materialCategories = {
+	'consumables (luxury)': [
+		'ALE',
+		'COF',
+		'GIN',
+		'KOM',
+		'NST',
+		'PWO',
+		'REP',
+		'SC',
+		'VG',
+		'WIN'
+	],
+	'ship engines': [
+		'AEN',
+		'AFP',
+		'AFR',
+		'ANZ',
+		'BFP',
+		'BFR',
+		'CHA',
+		'ENG',
+		'FIR',
+		'FSE',
+		'GCH',
+		'GEN',
+		'GNZ',
+		'HNZ',
+		'HPR',
+		'HTE',
+		'HYR',
+		'LFE',
+		'LFP',
+		'MFE',
+		'NOZ',
+		'QCR',
+		'RAG',
+		'RCS',
+		'RCT',
+		'SFE'
+	],
+	'software tools': [
+		'DA',
+		'DD',
+		'DV',
+		'EDC',
+		'NN',
+		'OS'
+	],
+	'construction parts': [
+		'AEF',
+		'AIR',
+		'DEC',
+		'FC',
+		'FLO',
+		'FLP',
+		'GC',
+		'GV',
+		'LIT',
+		'MGC',
+		'MHL',
+		'PSH',
+		'RSH',
+		'TCS',
+		'TRU',
+		'TSH'
+	],
+	'alloys': [
+		'AST',
+		'BGO',
+		'BOS',
+		'BRO',
+		'FAL',
+		'FET',
+		'RGO',
+		'WAL'
+	],
+	'consumable bundles': [
+		'CBU',
+		'EBU',
+		'PBU',
+		'SBU',
+		'TBU'
+	],
+	'medical equipment': [
+		'ADR',
+		'BND',
+		'PK',
+		'SEQ',
+		'STR',
+		'TUB'
+	],
+	'electronic parts': [
+		'CD',
+		'DIS',
+		'FAN',
+		'MB',
+		'MPC',
+		'PCB',
+		'RAM',
+		'ROM',
+		'SEN',
+		'TPU',
+		'TRA'
+	],
+	'energy systems': [
+		'CBL',
+		'CBM',
+		'CBS',
+		'POW',
+		'SOL',
+		'SP'
+	],
+	'minerals': [
+		'BER',
+		'BOR',
+		'BRM',
+		'CLI',
+		'GAL',
+		'HAL',
+		'LST',
+		'MAG',
+		'MGS',
+		'SCR',
+		'TAI',
+		'TCO',
+		'TS',
+		'ZIR'
+	],
+	'construction materials': [
+		'CMK',
+		'EPO',
+		'GL',
+		'INS',
+		'MCG',
+		'MTC',
+		'NCS',
+		'NFI',
+		'NG',
+		'RG',
+		'SEA'
+	],
+	'consumables (basic)': [
+		'DW',
+		'EXO',
+		'FIM',
+		'HMS',
+		'HSS',
+		'LC',
+		'MEA',
+		'MED',
+		'OVE',
+		'PDA',
+		'PT',
+		'RAT',
+		'SCN',
+		'WS'
+	],
+	'software systems': [
+		'IDC',
+		'IMM',
+		'SNM',
+		'WAI'
+	],
+	'electronic pieces': [
+		'BCO',
+		'BGC',
+		'CAP',
+		'HCC',
+		'LDI',
+		'MFK',
+		'MWF',
+		'SFK',
+		'SWF',
+		'TRN'
+	],
+	'software components': [
+		'BAI',
+		'LD',
+		'MLI',
+		'NF',
+		'SA',
+		'SAL',
+		'WM'
+	],
+	'ores': [
+		'ALO',
+		'AUO',
+		'CUO',
+		'FEO',
+		'LIO',
+		'SIO',
+		'TIO'
+	],
+	'unit prefabs': [
+		'BR1',
+		'BR2',
+		'BRS',
+		'CQL',
+		'CQM',
+		'CQS',
+		'CQT',
+		'DOU',
+		'FUN',
+		'HAB',
+		'LU',
+		'RDL',
+		'RDS',
+		'SU',
+		'TCU',
+		'WOR'
+	],
+	'ship shields': [
+		'APT',
+		'ARP',
+		'AWH',
+		'BPT',
+		'BRP',
+		'BWH',
+		'SRP'
+	],
+	'electronic devices': [
+		'AAR',
+		'AWF',
+		'BID',
+		'BMF',
+		'BSC',
+		'BWS',
+		'HD',
+		'HOG',
+		'HPC',
+		'MHP',
+		'RAD',
+		'SAR'
+	],
+	'metals': [
+		'AL',
+		'AU',
+		'CU',
+		'FE',
+		'LI',
+		'SI',
+		'STL',
+		'TI',
+		'W'
+	],
+	'electronic systems': [
+		'ACS',
+		'ADS',
+		'CC',
+		'COM',
+		'CRU',
+		'FFC',
+		'LIS',
+		'LOG',
+		'STS',
+		'TAC',
+		'WR'
+	],
+	'textiles': [
+		'CF',
+		'COT',
+		'CTF',
+		'KV',
+		'NL',
+		'SIL',
+		'TK'
+	],
+	'plastics': [
+		'DCL',
+		'DCM',
+		'DCS',
+		'PE',
+		'PG',
+		'PSL',
+		'PSM',
+		'PSS'
+	],
+	'chemicals': [
+		'BAC',
+		'BL',
+		'BLE',
+		'CST',
+		'DDT',
+		'EES',
+		'ETC',
+		'FLX',
+		'IND',
+		'JUI',
+		'LCR',
+		'NAB',
+		'NR',
+		'NS',
+		'OLF',
+		'PFE',
+		'REA',
+		'SOI',
+		'TCL',
+		'THF'
+	],
+	'elements': [
+		'BE',
+		'C',
+		'CA',
+		'CL',
+		'ES',
+		'I',
+		'MG',
+		'NA',
+		'S',
+		'TA',
+		'TC',
+		'ZR'
+	],
+	'gases': [
+		'AMM',
+		'AR',
+		'F',
+		'H',
+		'HE',
+		'HE3',
+		'N',
+		'NE',
+		'O'
+	],
+	'ship parts': [
+		'AGS',
+		'AHP',
+		'ATP',
+		'BGS',
+		'BHP',
+		'HHP',
+		'LHP',
+		'NV1',
+		'NV2',
+		'RHP',
+		'SSC',
+		'THP'
+	],
+	'drones': [
+		'CCD',
+		'DCH',
+		'DRF',
+		'RED',
+		'SDR',
+		'SRD',
+		'SUD'
+	],
+	'agricultural products': [
+		'ALG',
+		'BEA',
+		'CAF',
+		'FOD',
+		'GRA',
+		'GRN',
+		'HCP',
+		'HER',
+		'HOP',
+		'MAI',
+		'MTP',
+		'MUS',
+		'NUT',
+		'PIB',
+		'PPA',
+		'RCO',
+		'RSI',
+		'VEG',
+		'VIT'
+	],
+	'construction prefabs': [
+		'ABH',
+		'ADE',
+		'ASE',
+		'ATA',
+		'BBH',
+		'BDE',
+		'BSE',
+		'BTA',
+		'HSE',
+		'LBH',
+		'LDE',
+		'LSE',
+		'LTA',
+		'RBH',
+		'RDE',
+		'RSE',
+		'RTA'
+	],
+	'fuels': [
+		'FF',
+		'SF'
+	],
+	'ship kits': [
+		'HCB',
+		'LCB',
+		'LFL',
+		'LSL',
+		'MCB',
+		'MFL',
+		'MSL',
+		'SCB',
+		'SFL',
+		'SSL',
+		'TCB',
+		'VCB',
+		'VSC',
+		'WCB'
+	],
+	'liquids': [
+		'BTS',
+		'H2O',
+		'HEX',
+		'LES'
+	],
+	'utility': [
+		'OFF',
+		'SUN',
+		'UTS'
+	]
+}
+
+var materialsToCategories = {};
+for (const category in materialCategories) {
+	for (const material of materialCategories[category]) {
+		materialsToCategories[material] = category;
+	}
+}
+
+const materialCategoryColors = {
+	"agricultural products": "#752b2b",
+	"alloys": "#946537",
+	"chemicals": "#d04774",
+	"construction materials": "#3174ec",
+	"construction parts": "#426684",
+	"construction prefabs": "#28377b",
+	"consumable bundles": "#57232a",
+	"consumables (basic)": "#ae4747",
+	"consumables (luxury)": "#a13140",
+	"drones": "#a54d2b",
+	"electronic devices": "#6f2dac",
+	"electronic parts": "#7447d0",
+	"electronic pieces": "#906bd6",
+	"electronic systems": "#4c3365",
+	"elements": "#564739",
+	"energy systems": "#2e5740",
+	"fuels": "#379437",
+	"gases": "#198284",
+	"liquids": "#8bbde3",
+	"medical equipment": "#6ec36e",
+	"metals": "#4f4f4f",
+	"minerals": "#b28a62",
+	"ores": "#6b707a",
+	"plastics": "#923855",
+	"ship engines": "#b24219",
+	"ship kits": "#b26d19",
+	"ship parts": "#b27c19",
+	"ship shields": "#f99c19",
+	"software components": "#a19248",
+	"software systems": "#554e1e",
+	"software tools": "#9a7b2c",
+	"textiles": "#6b733a",
+	"unit prefabs": "#363435",
+	"utility": "#baada1"
+};
+
+var materialsToColors = {};
+for (const category in materialCategories) {
+	for (const material of materialCategories[category]) {
+		materialsToColors[material] = materialCategoryColors[category] || '#000000';
+	}
+}