파일 이식(0.31.1)
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import bs from 'binary-search';
|
||||
|
||||
const connectMap: [number, string][] = [
|
||||
[0, '안함'],
|
||||
[50, '무관심'],
|
||||
[100, '보통'],
|
||||
[400, '가끔'],
|
||||
[200, '자주'],
|
||||
[800, '열심'],
|
||||
[1600, '중독'],
|
||||
[3200, '폐인'],
|
||||
[6400, '경고'],
|
||||
[12800, '헐...'],
|
||||
]
|
||||
|
||||
export function formatConnectScore(connect: number) {
|
||||
const idx = bs(connectMap, connect, ([key], needle) => key - needle);
|
||||
if (idx >= 0) {
|
||||
return connectMap[idx][1] ?? '?';
|
||||
}
|
||||
return connectMap[-(idx + 1)][1] ?? '?';
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import bs from 'binary-search';
|
||||
|
||||
const defenceMap: [number,string][] = [
|
||||
[0, "△"],
|
||||
[60, "○"],
|
||||
[80, "◎"],
|
||||
[90, "☆"],
|
||||
[999, "×"],
|
||||
]
|
||||
|
||||
export function formatDefenceTrain(defenceTrain: number): string {
|
||||
const idx = bs(defenceMap, defenceTrain, ([defenceKey], needle) => defenceKey - needle);
|
||||
if(idx >= 0){
|
||||
return defenceMap[idx][1]??'?';
|
||||
}
|
||||
return defenceMap[-(idx + 1)][1]??'?';
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import bs from 'binary-search';
|
||||
|
||||
export const DexLevelMap: [number, string, string][] = [
|
||||
[0, 'navy', 'F-'],
|
||||
[350, 'navy', 'F'],
|
||||
[1375, 'navy', 'F+'],
|
||||
[3500, 'skyblue', 'E-'],
|
||||
[7125, 'skyblue', 'E'],
|
||||
[12650, 'skyblue', 'E+'],
|
||||
[20475, 'seagreen', 'D-'],
|
||||
[31000, 'seagreen', 'D'],
|
||||
[44625, 'seagreen', 'D+'],
|
||||
[61750, 'teal', 'C-'],
|
||||
[82775, 'teal', 'C'],
|
||||
[108100, 'teal', 'C+'],
|
||||
[138125, 'limegreen', 'B-'],
|
||||
[173250, 'limegreen', 'B'],
|
||||
[213875, 'limegreen', 'B+'],
|
||||
[260400, 'darkorange', 'A-'],
|
||||
[313225, 'darkorange', 'A'],
|
||||
[372750, 'darkorange', 'A+'],
|
||||
[439375, 'tomato', 'S-'],
|
||||
[513500, 'tomato', 'S'],
|
||||
[595525, 'tomato', 'S+'],
|
||||
[685850, 'darkviolet', 'Z-'],
|
||||
[784875, 'darkviolet', 'Z'],
|
||||
[893000, 'darkviolet', 'Z+'],
|
||||
[1010625, 'gold', 'EX-'],
|
||||
[1138150, 'gold', 'EX'],
|
||||
[1275975, 'white', 'EX+'],
|
||||
];
|
||||
|
||||
export type DexInfo = {
|
||||
level: number,
|
||||
name: string,
|
||||
color: string,
|
||||
}
|
||||
|
||||
export function formatDexLevel(dex: number): DexInfo {
|
||||
const rawIdx = bs(DexLevelMap, dex, ([dexKey], needle) => dexKey - needle);
|
||||
const level = rawIdx >= 0 ? rawIdx : -(rawIdx + 1);
|
||||
|
||||
const [, color, name] = DexLevelMap[level];
|
||||
|
||||
return {
|
||||
level,
|
||||
name,
|
||||
color
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { GameConstType } from "@/defs/GameObj";
|
||||
|
||||
export function formatGeneralTypeCall(leadership: number, strength: number, intel: number, gameConst: GameConstType): string {
|
||||
if (leadership < 40) {
|
||||
if (strength + intel < 40) {
|
||||
return '아둔';
|
||||
}
|
||||
if (intel >= gameConst.chiefStatMin && strength < intel * 0.8) {
|
||||
return '학자';
|
||||
}
|
||||
if (strength >= gameConst.chiefStatMin && intel < strength * 0.8) {
|
||||
return '장사';
|
||||
}
|
||||
return '명사';
|
||||
}
|
||||
|
||||
const maxStat = Math.max(leadership, strength, intel);
|
||||
const sum2Stat = Math.min(leadership + strength, strength + intel, intel + leadership);
|
||||
if (maxStat >= gameConst.chiefStatMin + gameConst.statGradeLevel && sum2Stat >= maxStat * 1.7) {
|
||||
return '만능';
|
||||
}
|
||||
if (strength >= gameConst.chiefStatMin - gameConst.statGradeLevel && intel < strength * 0.8) {
|
||||
return '용장';
|
||||
}
|
||||
if (intel >= gameConst.chiefStatMin - gameConst.statGradeLevel && strength < intel * 0.8) {
|
||||
return '명장';
|
||||
}
|
||||
if (leadership >= gameConst.chiefStatMin - gameConst.statGradeLevel && strength + intel < leadership) {
|
||||
return '차장';
|
||||
}
|
||||
return '평범';
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import bs from 'binary-search';
|
||||
|
||||
const hornorMap: [number, string][] = [
|
||||
[0, '전무'],
|
||||
[640, '무명'],
|
||||
[2560, '신동'],
|
||||
[5760, '약간'],
|
||||
[10240, '평범'],
|
||||
[16000, '지역적'],
|
||||
[23040, '전국적'],
|
||||
[31360, '세계적'],
|
||||
[40960, '유명'],
|
||||
[45000, '명사'],
|
||||
[51840, '호걸'],
|
||||
[55000, '효웅'],
|
||||
[64000, '영웅'],
|
||||
[77440, '구세주'],
|
||||
]
|
||||
|
||||
export function formatHonor(experience: number): string {
|
||||
const idx = bs(hornorMap, experience, ([experienceKey], needle) => experienceKey - needle);
|
||||
if (idx >= 0) {
|
||||
return hornorMap[idx][1] ?? '?';
|
||||
}
|
||||
return hornorMap[-(idx + 1)][1] ?? '?';
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export function formatInjury(injury: number): [string, string]{
|
||||
if(injury <= 0){
|
||||
return ['건강', 'white'];
|
||||
}
|
||||
if(injury <= 20){
|
||||
return ['경상', 'yellow'];
|
||||
}
|
||||
if(injury <= 40){
|
||||
return ['중상', 'orange'];
|
||||
}
|
||||
if(injury <= 60){
|
||||
return ['심각', 'magenta'];
|
||||
}
|
||||
return ['위독', 'red'];
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
const regex = /<([RBGMCLSODYW]1?|1|\/)>/g;
|
||||
|
||||
//TODO: <R>에서 더 확장해서, <R|G>, <R|N> 형태로 뒤에 타입을 지정할 수 있도록 한다.
|
||||
|
||||
const convertMap: Record<string, string> = {
|
||||
"R": 'color: red;',
|
||||
"B": 'color: blue;',
|
||||
"G": 'color: green;',
|
||||
"M": 'color: magenta;',
|
||||
"C": 'color: cyan;',
|
||||
"L": 'color: limegreen;',
|
||||
"S": 'color: skyblue;',
|
||||
"O": 'color: orangered;',
|
||||
"D": 'color: orangered;',
|
||||
"Y": 'color: yellow;',
|
||||
"W": 'color: white;',
|
||||
"1": 'font-size: 0.9em;',
|
||||
}
|
||||
|
||||
const convertMap2: Record<string, string> = {
|
||||
"1": 'font-size: 0.9em;',
|
||||
}
|
||||
|
||||
export function formatLog(text?: string): string {
|
||||
if (!text) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let matchRes;
|
||||
let lastIndex = 0;
|
||||
const result = [];
|
||||
while ((matchRes = regex.exec(text)) !== null) {
|
||||
const {
|
||||
0: partAll,
|
||||
1: subPart,
|
||||
index,
|
||||
} = matchRes;
|
||||
if (lastIndex != index) {
|
||||
result.push(text.slice(lastIndex, index));
|
||||
}
|
||||
|
||||
if (subPart == '/') {
|
||||
result.push(`</span>`);
|
||||
}
|
||||
else if (subPart.length == 2) {
|
||||
result.push(`<span style="${convertMap[subPart[0]] ?? ''}${convertMap2[subPart[1]] ?? ''}">`);
|
||||
}
|
||||
else {
|
||||
result.push(`<span style="${convertMap[subPart] ?? ''}">`);
|
||||
}
|
||||
|
||||
lastIndex = index + partAll.length;
|
||||
}
|
||||
|
||||
if (lastIndex != text.length) {
|
||||
result.push(text.slice(lastIndex));
|
||||
}
|
||||
|
||||
return result.join('');
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
export const OfficerLevelMapDefault: Record<number, string> = {
|
||||
12: '군주',
|
||||
11: '참모',
|
||||
10: '제1장군',
|
||||
9: '제1모사',
|
||||
8: '제2장군',
|
||||
7: '제2모사',
|
||||
6: '제3장군',
|
||||
5: '제3모사',
|
||||
4: '태수',
|
||||
3: '군사',
|
||||
2: '종사',
|
||||
1: '일반',
|
||||
0: '재야',
|
||||
}
|
||||
|
||||
export const OfficerLevelMapByNationLevel: Record<number, Record<number, string>> = {
|
||||
7: {
|
||||
12: '황제',
|
||||
11: '승상',
|
||||
10: '표기장군',
|
||||
9: '사공',
|
||||
8: '거기장군',
|
||||
7: '태위',
|
||||
6: '위장군',
|
||||
5: '사도'
|
||||
},
|
||||
|
||||
6: {
|
||||
12: '왕',
|
||||
11: '광록훈',
|
||||
10: '좌장군',
|
||||
9: '상서령',
|
||||
8: '우장군',
|
||||
7: '중서령',
|
||||
6: '전장군',
|
||||
5: '비서령'
|
||||
},
|
||||
|
||||
5: {
|
||||
12: '공',
|
||||
11: '광록대부',
|
||||
10: '안국장군',
|
||||
9: '집금오',
|
||||
8: '파로장군',
|
||||
7: '소부'
|
||||
},
|
||||
|
||||
4: {
|
||||
12: '주목',
|
||||
11: '태사령',
|
||||
10: '아문장군',
|
||||
9: '낭중',
|
||||
8: '호군',
|
||||
7: '종사중랑'
|
||||
},
|
||||
|
||||
3: {
|
||||
12: '주자사',
|
||||
11: '주부',
|
||||
10: '편장군',
|
||||
9: '간의대부'
|
||||
},
|
||||
|
||||
2: {
|
||||
12: '군벌',
|
||||
11: '참모',
|
||||
10: '비장군',
|
||||
9: '부참모'
|
||||
},
|
||||
|
||||
1: {
|
||||
12: '영주',
|
||||
11: '참모'
|
||||
},
|
||||
|
||||
0: {
|
||||
12: '두목',
|
||||
11: '부두목'
|
||||
},
|
||||
}
|
||||
export function formatOfficerLevelText(officerLevel: number, nationLevel?: number) {
|
||||
if (officerLevel < 5) {
|
||||
return OfficerLevelMapDefault[officerLevel] ?? '???';
|
||||
}
|
||||
|
||||
const nationMap = nationLevel === undefined
|
||||
? OfficerLevelMapDefault
|
||||
: (OfficerLevelMapByNationLevel[nationLevel] ?? OfficerLevelMapDefault);
|
||||
|
||||
return nationMap[officerLevel] ?? (OfficerLevelMapDefault[officerLevel] ?? '???');
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import _colorNames from 'css-color-names';
|
||||
|
||||
const colorNames = _colorNames as Record<string, string>;
|
||||
|
||||
const colors: string[] = [
|
||||
"red", "orange", "yellow", "green", "blue", "navy", "purple"
|
||||
].map(color => colorNames[color]);
|
||||
|
||||
export function formatVoteColor(type: number): string {
|
||||
return colors[type % colors.length];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export function nextExpLevelRemain(exp: number, expLevel: number): [number, number] {
|
||||
if (exp < 1000) {
|
||||
return [exp - expLevel * 100, 100]
|
||||
}
|
||||
|
||||
const expBase = 10 * expLevel ** 2;
|
||||
const expNext = 10 * (expLevel + 1) ** 2;
|
||||
return [exp - expBase, expNext - expBase];
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
import { clamp } from "lodash";
|
||||
|
||||
export const TECH_LEVEL_YEAR_GAP = 5;
|
||||
export const TECH_LEVEL_STEP = 1000;
|
||||
|
||||
export function isTechLimited(startYear: number, year: number, tech: number, maxTechLevel: number): boolean {
|
||||
const relMaxTech = getMaxRelativeTechLevel(startYear, year, maxTechLevel);
|
||||
const techLevel = convTechLevel(tech, maxTechLevel);
|
||||
|
||||
return techLevel >= relMaxTech;
|
||||
}
|
||||
|
||||
export function convTechLevel(tech: number, maxTechLevel: number): number{
|
||||
return clamp(Math.floor(tech / TECH_LEVEL_STEP), 0, maxTechLevel);
|
||||
}
|
||||
|
||||
|
||||
export function getMaxRelativeTechLevel(startYear: number, year: number, maxTechLevel: number): number {
|
||||
const relYear = year - startYear;
|
||||
return clamp(Math.floor(relYear / TECH_LEVEL_YEAR_GAP) + 1, 1, maxTechLevel);
|
||||
}
|
||||
Reference in New Issue
Block a user