wip
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
import type { LoginCtx } from "./ReqLogin.js";
|
||||
import type { SessionCtx } from "./StartSession.js";
|
||||
import type { ProcDecoratorGenerator } from "./base.js";
|
||||
|
||||
export type GameLoginCtx = {
|
||||
generalID: number;
|
||||
generalName: string;
|
||||
gameLoginDate: Date;
|
||||
}
|
||||
|
||||
export function ReqGameLogin<Q extends LoginCtx & SessionCtx>(): ProcDecoratorGenerator<GameLoginCtx, Q> {
|
||||
return async (ctx) => {
|
||||
//NOTE: 게임 서버별로 gameLoginCtx를 따로 가져야 하는가?
|
||||
let gameLoginCtx = ctx.session.getItem<GameLoginCtx>(`gameLoginCtx`);
|
||||
if(gameLoginCtx){
|
||||
if(gameLoginCtx.gameLoginDate >= ctx.loginDate){
|
||||
return [{
|
||||
result: true,
|
||||
},{
|
||||
...gameLoginCtx,
|
||||
...ctx,
|
||||
}];
|
||||
}
|
||||
gameLoginCtx = undefined;
|
||||
}
|
||||
|
||||
//TODO: DB에서 generalID를 가져오는 로직
|
||||
|
||||
return [{
|
||||
result: false,
|
||||
type: 'Required GameLogin',
|
||||
info: 'NotYetImplemented'
|
||||
}, ctx];
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import type { GatewayActionType, ServerActionType } from "../schema/gateway/User.js";
|
||||
import type { SessionCtx } from "./StartSession.js";
|
||||
import type { ProcDecorator } from "./base.js";
|
||||
|
||||
export type GatewayLoginCtx = {
|
||||
userID: number;
|
||||
userName: string;
|
||||
userLevel: number;
|
||||
allowServerAction: Map<string, Set<ServerActionType>>;
|
||||
allowGatewayAction: Set<GatewayActionType>;
|
||||
loginDate: Date;
|
||||
}
|
||||
export const loginCtxSessionKey = 'loginCtx';
|
||||
|
||||
export function ReqGatewayLogin<Q extends SessionCtx>(): ProcDecorator<GatewayLoginCtx & Q, Q> {
|
||||
return (ctx) => {
|
||||
const loginCtx = ctx.session.getItem<GatewayLoginCtx>(loginCtxSessionKey);
|
||||
if(!loginCtx){
|
||||
return [{
|
||||
result: false,
|
||||
type: 'Required Login',
|
||||
info: 'ReqLogin'
|
||||
}, ctx];
|
||||
}
|
||||
|
||||
return [{
|
||||
result: true,
|
||||
},{
|
||||
...loginCtx,
|
||||
...ctx,
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import type { ServerActionType } from "../schema/gateway/User.js";
|
||||
import type { SessionCtx } from "./StartSession.js";
|
||||
import type { ProcDecorator } from "./base.js";
|
||||
|
||||
export type LoginCtx = {
|
||||
userID: number;
|
||||
userName: string;
|
||||
userLevel: number;
|
||||
allowServerAction?: Set<ServerActionType>;
|
||||
loginDate: Date;
|
||||
}
|
||||
export const loginCtxSessionKey = 'loginCtx';
|
||||
|
||||
export function ReqLogin<Q extends SessionCtx>(): ProcDecorator<LoginCtx & Q, Q> {
|
||||
return (ctx) => {
|
||||
const loginCtx = ctx.session.getItem<LoginCtx>(loginCtxSessionKey);
|
||||
if(!loginCtx){
|
||||
return [{
|
||||
result: false,
|
||||
type: 'Required Login',
|
||||
info: 'ReqLogin'
|
||||
}, ctx];
|
||||
}
|
||||
|
||||
return [{
|
||||
result: true,
|
||||
},{
|
||||
...loginCtx,
|
||||
...ctx,
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { type Session, type SessionData } from "express-session";
|
||||
import type { Empty, ProcDecoratorGenerator } from "./base.js";
|
||||
|
||||
export type SessionCtx = {
|
||||
session: {
|
||||
clear: () => Promise<void>;
|
||||
removeItem: (key: string) => boolean;
|
||||
getItem: <T>(key: string) => T | undefined;
|
||||
setItem: (key: string, value: unknown) => void;
|
||||
raw: Session & Partial<SessionData> & Record<string, unknown>;
|
||||
}
|
||||
}
|
||||
|
||||
export function StartSession<Q extends object = Empty>(): ProcDecoratorGenerator<SessionCtx, Q> {
|
||||
return (inCtx, req) => {
|
||||
if (!req.session) {
|
||||
throw 'Express-session required';
|
||||
}
|
||||
const sessionObj = {
|
||||
raw: req.session
|
||||
} as SessionCtx['session'];
|
||||
sessionObj.clear = () => {
|
||||
return new Promise((resolve) => {
|
||||
sessionObj.raw = req.session.regenerate(resolve) as SessionCtx['session']['raw'];
|
||||
})
|
||||
}
|
||||
sessionObj.removeItem = (key: string): boolean => {
|
||||
if (key in sessionObj.raw) {
|
||||
delete sessionObj.raw[key];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
sessionObj.getItem = <T>(key: string): T | undefined => {
|
||||
if (!(key in sessionObj.raw)) {
|
||||
return undefined;
|
||||
}
|
||||
return sessionObj.raw[key] as T;
|
||||
}
|
||||
sessionObj.setItem = <T>(key: string, value: T | undefined): void => {
|
||||
if (value === undefined) {
|
||||
sessionObj.removeItem(key);
|
||||
return;
|
||||
}
|
||||
sessionObj.raw[key] = value;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
session: sessionObj,
|
||||
...inCtx,
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
import type { Request, Response } from "express";
|
||||
|
||||
type MayBePromise<T> = T | Promise<T>;
|
||||
|
||||
export type Empty = Record<string, never>;
|
||||
export type DecoratorResultTrue = {
|
||||
result: true;
|
||||
type?: string;
|
||||
info?: string;
|
||||
};
|
||||
export type DecoratorResultFalse = {
|
||||
result: false;
|
||||
type: string;
|
||||
info: string;
|
||||
}
|
||||
export type DecoratorResult = DecoratorResultTrue | DecoratorResultFalse;
|
||||
export type DecoratorStack = DecoratorResult[];
|
||||
|
||||
export interface ProcDecorator<Out extends object, In = Empty> {
|
||||
(inCtx: In & Partial<Out>, req: Request, res: Response)
|
||||
: MayBePromise<[DecoratorResultTrue, Out] | [DecoratorResultFalse, In & Partial<Out>]>;
|
||||
}
|
||||
|
||||
export interface PostProcDecorator<T extends object> {
|
||||
(ctx: T, preResult: DecoratorResult, req: Request, res: Response, isValidRoute: boolean): MayBePromise<[DecoratorResult, T]>;
|
||||
}
|
||||
|
||||
export interface ProcDecoratorRunner<Out extends object, In> {
|
||||
(inCtx: In, req: Request, res: Response): MayBePromise<[DecoratorStack, Out]>;
|
||||
}
|
||||
|
||||
export interface PostProcDecoratorRunner<T extends object> {
|
||||
(ctx: T, preResult: DecoratorStack, req: Request, res: Response, isValidRoute: boolean): MayBePromise<[DecoratorStack, T]>;
|
||||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type PlainDecorator = ProcDecorator<any, any>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type PlainPostDecorator = PostProcDecorator<any>;
|
||||
|
||||
|
||||
export type ProcDecoratorGenerator<Out extends object, In = Empty> = ProcDecorator<Out & In, In>;
|
||||
export type ProcDecoratorPrePostGenerator<Out extends object, In> = [ProcDecorator<Out & In, In>, PostProcDecorator<Out & In>];
|
||||
|
||||
export type ProcDecoratorChain = readonly ((() => PlainDecorator) | (() => [PlainDecorator, PlainPostDecorator]))[];
|
||||
|
||||
export type ResolveChain<T> = T extends undefined ? Empty : T extends ProcDecoratorChain ? Resolve<PackChain<T>> : never;
|
||||
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ParseInType<T> = T extends ProcDecorator<any, infer A> ? object extends A ? A : never : never;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ParseOutType<T> = T extends ProcDecorator<infer B, object> ? B : never;
|
||||
|
||||
export const EmptyProcDecorator: readonly [ProcDecoratorRunner<Empty, Empty>, PostProcDecoratorRunner<Empty>] = [
|
||||
async (ctx) => [[], ctx], async (ctx, stack) => [stack, ctx]
|
||||
];
|
||||
|
||||
export function declProcDecorators<T extends ProcDecoratorChain>(...decorators: T) {
|
||||
type OutType = Resolve<PackChain<T>>;
|
||||
|
||||
const preDecorator: PlainDecorator[] = [];
|
||||
const postDecorator: (PlainPostDecorator | undefined)[] = [];
|
||||
if (decorators) {
|
||||
for (const procGen of decorators) {
|
||||
const proc = procGen();
|
||||
if (Array.isArray(proc)) {
|
||||
preDecorator.push(proc[0]);
|
||||
postDecorator.push(proc[1]);
|
||||
}
|
||||
else {
|
||||
preDecorator.push(proc);
|
||||
postDecorator.push(undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const packedDecorators: readonly [ProcDecoratorRunner<OutType, Empty>, PostProcDecoratorRunner<OutType>] = [
|
||||
async (ctx, req, res) => {
|
||||
let rctx = ctx as unknown as OutType;
|
||||
const decoratorStack: DecoratorStack = [];
|
||||
if (!preDecorator.length) {
|
||||
return [decoratorStack, rctx];
|
||||
}
|
||||
|
||||
for (const [idx, proc] of preDecorator.entries()) {
|
||||
try {
|
||||
const [stackResult, newCtx] = await proc(rctx, req, res);
|
||||
decoratorStack.push(stackResult);
|
||||
|
||||
if (stackResult.result) {
|
||||
rctx = newCtx;
|
||||
continue;
|
||||
}
|
||||
|
||||
return [decoratorStack, newCtx];
|
||||
}
|
||||
catch (e) {
|
||||
while (decoratorStack.length > idx) {
|
||||
decoratorStack.pop();
|
||||
}
|
||||
decoratorStack.push({
|
||||
result: false,
|
||||
type: 'PreThrow',
|
||||
info: `internal error: ${e}`,
|
||||
});
|
||||
|
||||
return [decoratorStack, rctx];
|
||||
}
|
||||
}
|
||||
|
||||
return [decoratorStack, rctx];
|
||||
},
|
||||
async (ctx, stack, req, res) => {
|
||||
if (!postDecorator.length) {
|
||||
return [stack, ctx];
|
||||
}
|
||||
let isValidRoute = stack.length === postDecorator.length && stack.every(v => v.result);
|
||||
for (let idx = stack.length - 1; idx >= 0; idx--) {
|
||||
const preStackResult = stack[idx] as DecoratorResult;
|
||||
if (!preStackResult.result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const proc = postDecorator[idx];
|
||||
|
||||
if (!proc) {
|
||||
if (isValidRoute) {
|
||||
stack.pop();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const [postStackResult, nextCtx] = await proc(ctx, preStackResult, req, res, isValidRoute);
|
||||
if (postStackResult.result) {
|
||||
if (isValidRoute) {
|
||||
stack.pop();
|
||||
}
|
||||
ctx = nextCtx;
|
||||
continue;
|
||||
}
|
||||
|
||||
isValidRoute = false;
|
||||
stack[idx] = postStackResult;
|
||||
|
||||
ctx = nextCtx;
|
||||
}
|
||||
catch (e) {
|
||||
isValidRoute = false;
|
||||
stack[idx] = {
|
||||
result: false,
|
||||
type: 'PostThrow',
|
||||
info: `internal error: ${e}`,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
return [stack, ctx];
|
||||
},
|
||||
] as const;
|
||||
|
||||
return packedDecorators;
|
||||
}
|
||||
|
||||
type Compose2<D extends object, C, B, A = Empty> = B extends C ? ProcDecorator<D & B, A> : never;
|
||||
|
||||
type PD1<B extends object, A extends object> = () => ProcDecorator<B, A>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type PD2<B extends object, A extends object> = () => [ProcDecorator<B, A>, PostProcDecorator<any>];
|
||||
|
||||
export type PackChain<T> =
|
||||
T extends readonly [] ? ProcDecorator<Empty, Empty> :
|
||||
T extends readonly [PD1<infer B, infer A>] ? ProcDecorator<B, A> :
|
||||
T extends readonly [PD2<infer B, infer A>] ? ProcDecorator<B, A> :
|
||||
T extends readonly [PD1<infer B, infer A>, PD1<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<D, C, B, A>, ...R]> :
|
||||
T extends readonly [PD2<infer B, infer A>, PD1<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<D, C, B, A>, ...R]> :
|
||||
T extends readonly [PD1<infer B, infer A>, PD2<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<D, C, B, A>, ...R]> :
|
||||
T extends readonly [PD2<infer B, infer A>, PD2<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<D, C, B, A>, ...R]> :
|
||||
never;
|
||||
|
||||
type Resolve<T> = T extends ProcDecorator<infer B, infer A> ? Empty extends A ? B : never : never;
|
||||
@@ -1,38 +0,0 @@
|
||||
export function APIPathGen<T extends object, V>(
|
||||
obj: T,
|
||||
callback: (path: string[], tail: V, pathParam?: Record<string, string | number>) => unknown,
|
||||
path: string[] = [],
|
||||
): T {
|
||||
const map = new Map<string, unknown>();
|
||||
return new Proxy(obj, {
|
||||
get(target, key) {
|
||||
if(typeof key === 'symbol'){
|
||||
throw new Error('Symbol is not supported');
|
||||
}
|
||||
|
||||
const cachedResult = map.get(key);
|
||||
if(cachedResult !== undefined){
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
const nextPath = [...path, key];
|
||||
|
||||
let next: T[keyof T];
|
||||
if (key in target) {
|
||||
next = target[key as keyof typeof target];
|
||||
}
|
||||
else {
|
||||
throw `${nextPath} is not exists`;
|
||||
}
|
||||
|
||||
if (typeof (next) === 'function') {
|
||||
const result = callback(nextPath, next);
|
||||
map.set(key, result);
|
||||
return result;
|
||||
}
|
||||
const result = APIPathGen<T[keyof T], V>(next, callback, nextPath);
|
||||
map.set(key, result);
|
||||
return result;
|
||||
}
|
||||
}) as T;
|
||||
};
|
||||
@@ -1,95 +0,0 @@
|
||||
import isArray from "lodash-es/isArray";
|
||||
import isEmpty from "lodash-es/isEmpty";
|
||||
import ky from "ky";
|
||||
import type { HttpMethod, InvalidResponse, RawArgType, ValidResponse } from "../apiStructure/defs.js";
|
||||
|
||||
export async function callClientAPI<ResultType extends ValidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
paramArgs: Record<string, string | number> | undefined
|
||||
): Promise<ResultType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
paramArgs: Record<string, string | number> | undefined,
|
||||
returnError: undefined
|
||||
): Promise<ResultType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
paramArgs: Record<string, string | number> | undefined,
|
||||
returnError: false
|
||||
): Promise<ResultType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
paramArgs: Record<string, string | number> | undefined,
|
||||
returnError: true
|
||||
): Promise<ResultType | ErrorType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
paramArgs: Record<string, string | number> | undefined,
|
||||
returnError?: boolean
|
||||
): Promise<ResultType | ErrorType> {
|
||||
if (isArray(path)) {
|
||||
path = [apiRoot, ...path].join("/");
|
||||
}
|
||||
else if (path.startsWith("/")) {
|
||||
path = `${apiRoot}${path}`;
|
||||
}
|
||||
else {
|
||||
path = `${apiRoot}/${path}`;
|
||||
}
|
||||
|
||||
if (args && isEmpty(args)) {
|
||||
args = undefined;
|
||||
}
|
||||
|
||||
const result = (await (() => {
|
||||
if (method == "get") {
|
||||
return ky(path, {
|
||||
searchParams: {
|
||||
...paramArgs,
|
||||
...(args as typeof paramArgs),
|
||||
},
|
||||
method,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
timeout: 30000,
|
||||
retry: 0,
|
||||
});
|
||||
}
|
||||
return ky(path, {
|
||||
searchParams: {
|
||||
...paramArgs,
|
||||
},
|
||||
method,
|
||||
json: args,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
timeout: 30000,
|
||||
retry: 0,
|
||||
});
|
||||
})().json()) as ErrorType | ResultType;
|
||||
|
||||
if (!result.result) {
|
||||
if (returnError) {
|
||||
return result;
|
||||
}
|
||||
throw result.reason;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { APIPathGen } from "./APIPathGen.js";
|
||||
import type { APITail, RawArgType } from "../apiStructure/defs.js";
|
||||
import { structure } from "../apiStructure/sammoGatewayAPI.js";
|
||||
import { callClientAPI } from "./generator.js";
|
||||
|
||||
const apiRoot = process.env.API_ROOT_PATH ?? process.env.VITE_API_ROOT_PATH ?? '/rootAPI';
|
||||
|
||||
export const SammoGatewayAPI = APIPathGen(structure, (path: string[], tail: APITail, pathParam) => {
|
||||
const method = tail.reqType;
|
||||
return (args?: RawArgType, returnError?: boolean) => {
|
||||
if (returnError) {
|
||||
return callClientAPI(method, apiRoot, path.join('/'), args, pathParam, returnError);
|
||||
}
|
||||
return callClientAPI(method, apiRoot, path.join('/'), args, pathParam);
|
||||
};
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
import 'dotenv/config';
|
||||
import { connect, Mongoose } from "mongoose";
|
||||
import { unwrap } from './util/unwrap.js';
|
||||
|
||||
const dbConfig = {
|
||||
host: unwrap(process.env.GAME_DB_HOST),
|
||||
port: Number(unwrap(process.env.GAME_DB_PORT)),
|
||||
user: unwrap(process.env.GAME_DB_USER),
|
||||
password: unwrap(process.env.GAME_DB_PASSWORD),
|
||||
database: unwrap(process.env.GAME_DB_DATABASE),
|
||||
}
|
||||
|
||||
const db: Promise<Mongoose> = (async () => {
|
||||
return await connect(`mongodb://${dbConfig.host}:${dbConfig.port}/${dbConfig.database}`, {
|
||||
auth:{
|
||||
username: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
export default db;
|
||||
Vendored
-32
@@ -1,32 +0,0 @@
|
||||
declare namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
NODE_ENV: 'development' | 'production';
|
||||
|
||||
//Docker 환경이라면 GAME_DB 또는 GATEWAY_DB 둘중에 하나만 설정되어 있을 것이다.
|
||||
GAME_DB_HOST?: string;
|
||||
GAME_DB_DATABASE?: string;
|
||||
GAME_DB_PORT?: string;
|
||||
GAME_DB_USER?: string;
|
||||
GAME_DB_PASSWORD?: string;
|
||||
|
||||
GATEWAY_DB_HOST?: string;
|
||||
GATEWAY_DB_DATABASE?: string;
|
||||
GATEWAY_DB_PORT?: string;
|
||||
GATEWAY_DB_USER?: string;
|
||||
GATEWAY_DB_PASSWORD?: string;
|
||||
|
||||
//Gateway RPC용
|
||||
GATEWAY_HOST?: string;
|
||||
GATEWAY_PORT?: string;
|
||||
//gateway.ts용
|
||||
GATEWAY_SESSION_SECRET?: string;
|
||||
|
||||
SERVER_PORT?: string; //숫자
|
||||
SESSION_SECRET?: string; //길게
|
||||
|
||||
API_ROOT_PATH?: string;
|
||||
VITE_API_ROOT_PATH?: string;
|
||||
|
||||
PRESHARED_SECURE_TOKEN_SECRET?: string; //길게
|
||||
}
|
||||
}
|
||||
@@ -1,1079 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
|
||||
|
||||
/**
|
||||
* AUTO-GENERATED FILE @ 2023-08-05 12:06:36 - DO NOT EDIT!
|
||||
*
|
||||
* This file was automatically generated by schemats v.3.0.3
|
||||
* $ schemats generate -c mysql://username:password@127.0.0.1/hidche_hwe -C -t board -t city -t comment -t diplomacy -t emperior -t event -t general -t general_access_log -t general_record -t general_turn -t hall -t message -t nation -t nation_env -t nation_turn -t ng_auction -t ng_auction_bid -t ng_betting -t ng_diplomacy -t ng_games -t ng_history -t ng_old_generals -t ng_old_nations -t plock -t rank_data -t reserved_open -t select_npc_token -t select_pool -t statistic -t storage -t tournament -t troop -t user_record -t vote -t vote_comment -t world_history -s hidche_hwe
|
||||
*
|
||||
*/
|
||||
|
||||
export type EnumTarget = 'MONTH' | 'OCCUPY_CITY' | 'DESTROY_NATION' | 'PRE_MONTH' | 'UNITED';
|
||||
export type EnumAuctionType = 'buyRice' | 'sellRice' | 'uniqueItem';
|
||||
export type EnumReqResource = 'gold' | 'rice' | 'inheritPoint';
|
||||
export type EnumLogType = 'action' | 'battle_brief' | 'battle' | 'history';
|
||||
export type EnumMsgType = 'private' | 'national' | 'public' | 'diplomacy';
|
||||
export type EnumPermission = 'normal' | 'auditor' | 'ambassador';
|
||||
export type EnumType = 'GAME' | 'ETC' | 'TOURNAMENT';
|
||||
export type EnumState = 'proposed' | 'activated' | 'cancelled' | 'replaced';
|
||||
|
||||
export namespace BoardFields {
|
||||
export type no = number;
|
||||
export type nationNo = number;
|
||||
export type isSecret = boolean;
|
||||
export type date = Date;
|
||||
export type generalNo = number;
|
||||
export type author = string;
|
||||
export type authorIcon = string | null;
|
||||
export type title = string;
|
||||
export type text = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Board {
|
||||
no: BoardFields.no;
|
||||
nationNo: BoardFields.nationNo;
|
||||
isSecret: BoardFields.isSecret;
|
||||
date: BoardFields.date;
|
||||
generalNo: BoardFields.generalNo;
|
||||
author: BoardFields.author;
|
||||
authorIcon: BoardFields.authorIcon;
|
||||
title: BoardFields.title;
|
||||
text: BoardFields.text;
|
||||
|
||||
}
|
||||
|
||||
export namespace CityFields {
|
||||
export type city = number;
|
||||
export type name = string;
|
||||
export type level = number;
|
||||
export type nation = number;
|
||||
export type supply = number;
|
||||
export type front = number;
|
||||
export type pop = number;
|
||||
export type popMax = number;
|
||||
export type agri = number;
|
||||
export type agriMax = number;
|
||||
export type comm = number;
|
||||
export type commMax = number;
|
||||
export type secu = number;
|
||||
export type secuMax = number;
|
||||
export type trust = number;
|
||||
export type trade = number | null;
|
||||
export type dead = number;
|
||||
export type def = number;
|
||||
export type defMax = number;
|
||||
export type wall = number;
|
||||
export type wallMax = number;
|
||||
export type officerSet = number;
|
||||
export type state = number;
|
||||
export type region = number;
|
||||
export type term = number;
|
||||
export type conflict = string;
|
||||
|
||||
}
|
||||
|
||||
export interface City {
|
||||
city: CityFields.city;
|
||||
name: CityFields.name;
|
||||
level: CityFields.level;
|
||||
nation: CityFields.nation;
|
||||
supply: CityFields.supply;
|
||||
front: CityFields.front;
|
||||
pop: CityFields.pop;
|
||||
popMax: CityFields.popMax;
|
||||
agri: CityFields.agri;
|
||||
agriMax: CityFields.agriMax;
|
||||
comm: CityFields.comm;
|
||||
commMax: CityFields.commMax;
|
||||
secu: CityFields.secu;
|
||||
secuMax: CityFields.secuMax;
|
||||
trust: CityFields.trust;
|
||||
trade: CityFields.trade;
|
||||
dead: CityFields.dead;
|
||||
def: CityFields.def;
|
||||
defMax: CityFields.defMax;
|
||||
wall: CityFields.wall;
|
||||
wallMax: CityFields.wallMax;
|
||||
officerSet: CityFields.officerSet;
|
||||
state: CityFields.state;
|
||||
region: CityFields.region;
|
||||
term: CityFields.term;
|
||||
conflict: CityFields.conflict;
|
||||
|
||||
}
|
||||
|
||||
export namespace CommentFields {
|
||||
export type no = number;
|
||||
export type nationNo = number;
|
||||
export type isSecret = boolean;
|
||||
export type date = Date;
|
||||
export type documentNo = number;
|
||||
export type generalNo = number;
|
||||
export type author = string;
|
||||
export type text = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Comment {
|
||||
no: CommentFields.no;
|
||||
nationNo: CommentFields.nationNo;
|
||||
isSecret: CommentFields.isSecret;
|
||||
date: CommentFields.date;
|
||||
documentNo: CommentFields.documentNo;
|
||||
generalNo: CommentFields.generalNo;
|
||||
author: CommentFields.author;
|
||||
text: CommentFields.text;
|
||||
|
||||
}
|
||||
|
||||
export namespace DiplomacyFields {
|
||||
export type no = number;
|
||||
export type me = number;
|
||||
export type you = number;
|
||||
export type state = number | null;
|
||||
export type term = number | null;
|
||||
export type dead = number | null;
|
||||
export type showing = Date | null;
|
||||
|
||||
}
|
||||
|
||||
export interface Diplomacy {
|
||||
no: DiplomacyFields.no;
|
||||
me: DiplomacyFields.me;
|
||||
you: DiplomacyFields.you;
|
||||
state: DiplomacyFields.state;
|
||||
term: DiplomacyFields.term;
|
||||
dead: DiplomacyFields.dead;
|
||||
showing: DiplomacyFields.showing;
|
||||
|
||||
}
|
||||
|
||||
export namespace EmperiorFields {
|
||||
export type no = number;
|
||||
export type serverId = string | null;
|
||||
export type phase = string | null;
|
||||
export type nationCount = string | null;
|
||||
export type nationName = string | null;
|
||||
export type nationHist = string | null;
|
||||
export type genCount = string | null;
|
||||
export type personalHist = string | null;
|
||||
export type specialHist = string | null;
|
||||
export type name = string | null;
|
||||
export type type = string | null;
|
||||
export type color = string | null;
|
||||
export type year = number | null;
|
||||
export type month = number | null;
|
||||
export type power = number | null;
|
||||
export type gennum = number | null;
|
||||
export type citynum = number | null;
|
||||
export type pop = string | null;
|
||||
export type poprate = string | null;
|
||||
export type gold = number | null;
|
||||
export type rice = number | null;
|
||||
export type l12Name = string | null;
|
||||
export type l12Pic = string | null;
|
||||
export type l11Name = string | null;
|
||||
export type l11Pic = string | null;
|
||||
export type l10Name = string | null;
|
||||
export type l10Pic = string | null;
|
||||
export type l9Name = string | null;
|
||||
export type l9Pic = string | null;
|
||||
export type l8Name = string | null;
|
||||
export type l8Pic = string | null;
|
||||
export type l7Name = string | null;
|
||||
export type l7Pic = string | null;
|
||||
export type l6Name = string | null;
|
||||
export type l6Pic = string | null;
|
||||
export type l5Name = string | null;
|
||||
export type l5Pic = string | null;
|
||||
export type tiger = string | null;
|
||||
export type eagle = string | null;
|
||||
export type gen = string | null;
|
||||
export type history = string | null;
|
||||
export type aux = string | null;
|
||||
|
||||
}
|
||||
|
||||
export interface Emperior {
|
||||
no: EmperiorFields.no;
|
||||
serverId: EmperiorFields.serverId;
|
||||
phase: EmperiorFields.phase;
|
||||
nationCount: EmperiorFields.nationCount;
|
||||
nationName: EmperiorFields.nationName;
|
||||
nationHist: EmperiorFields.nationHist;
|
||||
genCount: EmperiorFields.genCount;
|
||||
personalHist: EmperiorFields.personalHist;
|
||||
specialHist: EmperiorFields.specialHist;
|
||||
name: EmperiorFields.name;
|
||||
type: EmperiorFields.type;
|
||||
color: EmperiorFields.color;
|
||||
year: EmperiorFields.year;
|
||||
month: EmperiorFields.month;
|
||||
power: EmperiorFields.power;
|
||||
gennum: EmperiorFields.gennum;
|
||||
citynum: EmperiorFields.citynum;
|
||||
pop: EmperiorFields.pop;
|
||||
poprate: EmperiorFields.poprate;
|
||||
gold: EmperiorFields.gold;
|
||||
rice: EmperiorFields.rice;
|
||||
l12Name: EmperiorFields.l12Name;
|
||||
l12Pic: EmperiorFields.l12Pic;
|
||||
l11Name: EmperiorFields.l11Name;
|
||||
l11Pic: EmperiorFields.l11Pic;
|
||||
l10Name: EmperiorFields.l10Name;
|
||||
l10Pic: EmperiorFields.l10Pic;
|
||||
l9Name: EmperiorFields.l9Name;
|
||||
l9Pic: EmperiorFields.l9Pic;
|
||||
l8Name: EmperiorFields.l8Name;
|
||||
l8Pic: EmperiorFields.l8Pic;
|
||||
l7Name: EmperiorFields.l7Name;
|
||||
l7Pic: EmperiorFields.l7Pic;
|
||||
l6Name: EmperiorFields.l6Name;
|
||||
l6Pic: EmperiorFields.l6Pic;
|
||||
l5Name: EmperiorFields.l5Name;
|
||||
l5Pic: EmperiorFields.l5Pic;
|
||||
tiger: EmperiorFields.tiger;
|
||||
eagle: EmperiorFields.eagle;
|
||||
gen: EmperiorFields.gen;
|
||||
history: EmperiorFields.history;
|
||||
aux: EmperiorFields.aux;
|
||||
|
||||
}
|
||||
|
||||
export namespace EventFields {
|
||||
export type id = number;
|
||||
export type target = EnumTarget;
|
||||
export type priority = number;
|
||||
export type condition = string;
|
||||
export type action = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
id: EventFields.id;
|
||||
target: EventFields.target;
|
||||
priority: EventFields.priority;
|
||||
condition: EventFields.condition;
|
||||
action: EventFields.action;
|
||||
|
||||
}
|
||||
|
||||
export namespace GeneralFields {
|
||||
export type no = number;
|
||||
export type owner = number;
|
||||
export type npcmsg = string | null;
|
||||
export type npc = number;
|
||||
export type npcOrg = number | null;
|
||||
export type affinity = number | null;
|
||||
export type bornyear = number | null;
|
||||
export type deadyear = number | null;
|
||||
export type newmsg = number | null;
|
||||
export type picture = string;
|
||||
export type imgsvr = number;
|
||||
export type name = string;
|
||||
export type ownerName = string | null;
|
||||
export type nation = number;
|
||||
export type city = number;
|
||||
export type troop = number;
|
||||
export type leadership = number;
|
||||
export type leadershipExp = number;
|
||||
export type strength = number;
|
||||
export type strengthExp = number;
|
||||
export type intel = number;
|
||||
export type intelExp = number;
|
||||
export type injury = number;
|
||||
export type experience = number;
|
||||
export type dedication = number;
|
||||
export type dex1 = number;
|
||||
export type dex2 = number;
|
||||
export type dex3 = number;
|
||||
export type dex4 = number;
|
||||
export type dex5 = number;
|
||||
export type officerLevel = number;
|
||||
export type officerCity = number;
|
||||
export type permission = EnumPermission | null;
|
||||
export type gold = number;
|
||||
export type rice = number;
|
||||
export type crew = number;
|
||||
export type crewtype = number;
|
||||
export type train = number;
|
||||
export type atmos = number;
|
||||
export type weapon = string;
|
||||
export type book = string;
|
||||
export type horse = string;
|
||||
export type item = string;
|
||||
export type turntime = Date;
|
||||
export type recentWar = Date | null;
|
||||
export type makelimit = number | null;
|
||||
export type killturn = number | null;
|
||||
export type block = number | null;
|
||||
export type dedlevel = number | null;
|
||||
export type explevel = number | null;
|
||||
export type age = number | null;
|
||||
export type startage = number | null;
|
||||
export type belong = number | null;
|
||||
export type betray = number | null;
|
||||
export type personal = string;
|
||||
export type special = string;
|
||||
export type specage = number | null;
|
||||
export type special2 = string;
|
||||
export type specage2 = number | null;
|
||||
export type defenceTrain = number | null;
|
||||
export type tnmt = number | null;
|
||||
export type myset = number | null;
|
||||
export type tournament = number | null;
|
||||
export type newvote = number | null;
|
||||
export type lastTurn = string;
|
||||
export type aux = string;
|
||||
export type penalty = string | null;
|
||||
|
||||
}
|
||||
|
||||
export interface General {
|
||||
no: GeneralFields.no;
|
||||
owner: GeneralFields.owner;
|
||||
npcmsg: GeneralFields.npcmsg;
|
||||
npc: GeneralFields.npc;
|
||||
npcOrg: GeneralFields.npcOrg;
|
||||
affinity: GeneralFields.affinity;
|
||||
bornyear: GeneralFields.bornyear;
|
||||
deadyear: GeneralFields.deadyear;
|
||||
newmsg: GeneralFields.newmsg;
|
||||
picture: GeneralFields.picture;
|
||||
imgsvr: GeneralFields.imgsvr;
|
||||
name: GeneralFields.name;
|
||||
ownerName: GeneralFields.ownerName;
|
||||
nation: GeneralFields.nation;
|
||||
city: GeneralFields.city;
|
||||
troop: GeneralFields.troop;
|
||||
leadership: GeneralFields.leadership;
|
||||
leadershipExp: GeneralFields.leadershipExp;
|
||||
strength: GeneralFields.strength;
|
||||
strengthExp: GeneralFields.strengthExp;
|
||||
intel: GeneralFields.intel;
|
||||
intelExp: GeneralFields.intelExp;
|
||||
injury: GeneralFields.injury;
|
||||
experience: GeneralFields.experience;
|
||||
dedication: GeneralFields.dedication;
|
||||
dex1: GeneralFields.dex1;
|
||||
dex2: GeneralFields.dex2;
|
||||
dex3: GeneralFields.dex3;
|
||||
dex4: GeneralFields.dex4;
|
||||
dex5: GeneralFields.dex5;
|
||||
officerLevel: GeneralFields.officerLevel;
|
||||
officerCity: GeneralFields.officerCity;
|
||||
permission: GeneralFields.permission;
|
||||
gold: GeneralFields.gold;
|
||||
rice: GeneralFields.rice;
|
||||
crew: GeneralFields.crew;
|
||||
crewtype: GeneralFields.crewtype;
|
||||
train: GeneralFields.train;
|
||||
atmos: GeneralFields.atmos;
|
||||
weapon: GeneralFields.weapon;
|
||||
book: GeneralFields.book;
|
||||
horse: GeneralFields.horse;
|
||||
item: GeneralFields.item;
|
||||
turntime: GeneralFields.turntime;
|
||||
recentWar: GeneralFields.recentWar;
|
||||
makelimit: GeneralFields.makelimit;
|
||||
killturn: GeneralFields.killturn;
|
||||
block: GeneralFields.block;
|
||||
dedlevel: GeneralFields.dedlevel;
|
||||
explevel: GeneralFields.explevel;
|
||||
age: GeneralFields.age;
|
||||
startage: GeneralFields.startage;
|
||||
belong: GeneralFields.belong;
|
||||
betray: GeneralFields.betray;
|
||||
personal: GeneralFields.personal;
|
||||
special: GeneralFields.special;
|
||||
specage: GeneralFields.specage;
|
||||
special2: GeneralFields.special2;
|
||||
specage2: GeneralFields.specage2;
|
||||
defenceTrain: GeneralFields.defenceTrain;
|
||||
tnmt: GeneralFields.tnmt;
|
||||
myset: GeneralFields.myset;
|
||||
tournament: GeneralFields.tournament;
|
||||
newvote: GeneralFields.newvote;
|
||||
lastTurn: GeneralFields.lastTurn;
|
||||
aux: GeneralFields.aux;
|
||||
penalty: GeneralFields.penalty;
|
||||
|
||||
}
|
||||
|
||||
export namespace GeneralAccessLogFields {
|
||||
export type id = number;
|
||||
export type generalId = number;
|
||||
export type userId = number | null;
|
||||
export type lastRefresh = Date | null;
|
||||
export type refresh = number;
|
||||
export type refreshTotal = number;
|
||||
export type refreshScore = number;
|
||||
export type refreshScoreTotal = number;
|
||||
|
||||
}
|
||||
|
||||
export interface GeneralAccessLog {
|
||||
id: GeneralAccessLogFields.id;
|
||||
generalId: GeneralAccessLogFields.generalId;
|
||||
userId: GeneralAccessLogFields.userId;
|
||||
lastRefresh: GeneralAccessLogFields.lastRefresh;
|
||||
refresh: GeneralAccessLogFields.refresh;
|
||||
refreshTotal: GeneralAccessLogFields.refreshTotal;
|
||||
refreshScore: GeneralAccessLogFields.refreshScore;
|
||||
refreshScoreTotal: GeneralAccessLogFields.refreshScoreTotal;
|
||||
|
||||
}
|
||||
|
||||
export namespace GeneralRecordFields {
|
||||
export type id = number;
|
||||
export type generalId = number;
|
||||
export type logType = EnumLogType;
|
||||
export type year = number;
|
||||
export type month = number;
|
||||
export type text = string;
|
||||
|
||||
}
|
||||
|
||||
export interface GeneralRecord {
|
||||
id: GeneralRecordFields.id;
|
||||
generalId: GeneralRecordFields.generalId;
|
||||
logType: GeneralRecordFields.logType;
|
||||
year: GeneralRecordFields.year;
|
||||
month: GeneralRecordFields.month;
|
||||
text: GeneralRecordFields.text;
|
||||
|
||||
}
|
||||
|
||||
export namespace GeneralTurnFields {
|
||||
export type id = number;
|
||||
export type generalId = number;
|
||||
export type turnIdx = number;
|
||||
export type action = string;
|
||||
export type arg = string | null;
|
||||
export type brief = string | null;
|
||||
|
||||
}
|
||||
|
||||
export interface GeneralTurn {
|
||||
id: GeneralTurnFields.id;
|
||||
generalId: GeneralTurnFields.generalId;
|
||||
turnIdx: GeneralTurnFields.turnIdx;
|
||||
action: GeneralTurnFields.action;
|
||||
arg: GeneralTurnFields.arg;
|
||||
brief: GeneralTurnFields.brief;
|
||||
|
||||
}
|
||||
|
||||
export namespace HallFields {
|
||||
export type id = number;
|
||||
export type serverId = string;
|
||||
export type season = number;
|
||||
export type scenario = number;
|
||||
export type generalNo = number;
|
||||
export type type = string;
|
||||
export type value = number;
|
||||
export type owner = number | null;
|
||||
export type aux = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Hall {
|
||||
id: HallFields.id;
|
||||
serverId: HallFields.serverId;
|
||||
season: HallFields.season;
|
||||
scenario: HallFields.scenario;
|
||||
generalNo: HallFields.generalNo;
|
||||
type: HallFields.type;
|
||||
value: HallFields.value;
|
||||
owner: HallFields.owner;
|
||||
aux: HallFields.aux;
|
||||
|
||||
}
|
||||
|
||||
export namespace MessageFields {
|
||||
export type id = number;
|
||||
export type mailbox = number;
|
||||
export type type = EnumMsgType;
|
||||
export type src = number;
|
||||
export type dest = number;
|
||||
export type time = Date;
|
||||
export type validUntil = Date;
|
||||
export type message = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
id: MessageFields.id;
|
||||
mailbox: MessageFields.mailbox;
|
||||
type: MessageFields.type;
|
||||
src: MessageFields.src;
|
||||
dest: MessageFields.dest;
|
||||
time: MessageFields.time;
|
||||
validUntil: MessageFields.validUntil;
|
||||
message: MessageFields.message;
|
||||
|
||||
}
|
||||
|
||||
export namespace NationFields {
|
||||
export type nation = number;
|
||||
export type name = string;
|
||||
export type color = string;
|
||||
export type capital = number | null;
|
||||
export type capset = number | null;
|
||||
export type gennum = number | null;
|
||||
export type gold = number | null;
|
||||
export type rice = number | null;
|
||||
export type bill = number | null;
|
||||
export type rate = number | null;
|
||||
export type rateTmp = number | null;
|
||||
export type secretlimit = number | null;
|
||||
export type chiefSet = number;
|
||||
export type scout = number | null;
|
||||
export type war = number | null;
|
||||
export type strategicCmdLimit = number | null;
|
||||
export type surlimit = number | null;
|
||||
export type tech = number | null;
|
||||
export type power = number | null;
|
||||
export type spy = string;
|
||||
export type level = number | null;
|
||||
export type type = string;
|
||||
export type aux = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Nation {
|
||||
nation: NationFields.nation;
|
||||
name: NationFields.name;
|
||||
color: NationFields.color;
|
||||
capital: NationFields.capital;
|
||||
capset: NationFields.capset;
|
||||
gennum: NationFields.gennum;
|
||||
gold: NationFields.gold;
|
||||
rice: NationFields.rice;
|
||||
bill: NationFields.bill;
|
||||
rate: NationFields.rate;
|
||||
rateTmp: NationFields.rateTmp;
|
||||
secretlimit: NationFields.secretlimit;
|
||||
chiefSet: NationFields.chiefSet;
|
||||
scout: NationFields.scout;
|
||||
war: NationFields.war;
|
||||
strategicCmdLimit: NationFields.strategicCmdLimit;
|
||||
surlimit: NationFields.surlimit;
|
||||
tech: NationFields.tech;
|
||||
power: NationFields.power;
|
||||
spy: NationFields.spy;
|
||||
level: NationFields.level;
|
||||
type: NationFields.type;
|
||||
aux: NationFields.aux;
|
||||
|
||||
}
|
||||
|
||||
export namespace NationEnvFields {
|
||||
export type id = number;
|
||||
export type namespace = number;
|
||||
export type key = string;
|
||||
export type value = string;
|
||||
|
||||
}
|
||||
|
||||
export interface NationEnv {
|
||||
id: NationEnvFields.id;
|
||||
namespace: NationEnvFields.namespace;
|
||||
key: NationEnvFields.key;
|
||||
value: NationEnvFields.value;
|
||||
|
||||
}
|
||||
|
||||
export namespace NationTurnFields {
|
||||
export type id = number;
|
||||
export type nationId = number;
|
||||
export type officerLevel = number;
|
||||
export type turnIdx = number;
|
||||
export type action = string;
|
||||
export type arg = string | null;
|
||||
export type brief = string | null;
|
||||
|
||||
}
|
||||
|
||||
export interface NationTurn {
|
||||
id: NationTurnFields.id;
|
||||
nationId: NationTurnFields.nationId;
|
||||
officerLevel: NationTurnFields.officerLevel;
|
||||
turnIdx: NationTurnFields.turnIdx;
|
||||
action: NationTurnFields.action;
|
||||
arg: NationTurnFields.arg;
|
||||
brief: NationTurnFields.brief;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgAuctionFields {
|
||||
export type id = number;
|
||||
export type type = EnumAuctionType;
|
||||
export type finished = Buffer;
|
||||
export type target = string | null;
|
||||
export type hostGeneralId = number;
|
||||
export type reqResource = EnumReqResource;
|
||||
export type openDate = Date;
|
||||
export type closeDate = Date;
|
||||
export type detail = string;
|
||||
|
||||
}
|
||||
|
||||
export interface NgAuction {
|
||||
id: NgAuctionFields.id;
|
||||
type: NgAuctionFields.type;
|
||||
finished: NgAuctionFields.finished;
|
||||
target: NgAuctionFields.target;
|
||||
hostGeneralId: NgAuctionFields.hostGeneralId;
|
||||
reqResource: NgAuctionFields.reqResource;
|
||||
openDate: NgAuctionFields.openDate;
|
||||
closeDate: NgAuctionFields.closeDate;
|
||||
detail: NgAuctionFields.detail;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgAuctionBidFields {
|
||||
export type no = number;
|
||||
export type auctionId = number;
|
||||
export type owner = number | null;
|
||||
export type generalId = number;
|
||||
export type amount = number;
|
||||
export type date = Date;
|
||||
export type aux = string;
|
||||
|
||||
}
|
||||
|
||||
export interface NgAuctionBid {
|
||||
no: NgAuctionBidFields.no;
|
||||
auctionId: NgAuctionBidFields.auctionId;
|
||||
owner: NgAuctionBidFields.owner;
|
||||
generalId: NgAuctionBidFields.generalId;
|
||||
amount: NgAuctionBidFields.amount;
|
||||
date: NgAuctionBidFields.date;
|
||||
aux: NgAuctionBidFields.aux;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgBettingFields {
|
||||
export type id = number;
|
||||
export type bettingId = number;
|
||||
export type generalId = number;
|
||||
export type userId = number | null;
|
||||
export type bettingType = string;
|
||||
export type amount = number;
|
||||
|
||||
}
|
||||
|
||||
export interface NgBetting {
|
||||
id: NgBettingFields.id;
|
||||
bettingId: NgBettingFields.bettingId;
|
||||
generalId: NgBettingFields.generalId;
|
||||
userId: NgBettingFields.userId;
|
||||
bettingType: NgBettingFields.bettingType;
|
||||
amount: NgBettingFields.amount;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgDiplomacyFields {
|
||||
export type no = number;
|
||||
export type srcNationId = number;
|
||||
export type destNationId = number;
|
||||
export type prevNo = number | null;
|
||||
export type state = EnumState;
|
||||
export type textBrief = string;
|
||||
export type textDetail = string;
|
||||
export type date = Date;
|
||||
export type srcSigner = number;
|
||||
export type destSigner = number | null;
|
||||
export type aux = string | null;
|
||||
|
||||
}
|
||||
|
||||
export interface NgDiplomacy {
|
||||
no: NgDiplomacyFields.no;
|
||||
srcNationId: NgDiplomacyFields.srcNationId;
|
||||
destNationId: NgDiplomacyFields.destNationId;
|
||||
prevNo: NgDiplomacyFields.prevNo;
|
||||
state: NgDiplomacyFields.state;
|
||||
textBrief: NgDiplomacyFields.textBrief;
|
||||
textDetail: NgDiplomacyFields.textDetail;
|
||||
date: NgDiplomacyFields.date;
|
||||
srcSigner: NgDiplomacyFields.srcSigner;
|
||||
destSigner: NgDiplomacyFields.destSigner;
|
||||
aux: NgDiplomacyFields.aux;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgGamesFields {
|
||||
export type id = number;
|
||||
export type serverId = string;
|
||||
export type date = Date;
|
||||
export type winnerNation = number | null;
|
||||
export type map = string | null;
|
||||
export type season = number;
|
||||
export type scenario = number;
|
||||
export type scenarioName = string;
|
||||
export type env = string;
|
||||
|
||||
}
|
||||
|
||||
export interface NgGames {
|
||||
id: NgGamesFields.id;
|
||||
serverId: NgGamesFields.serverId;
|
||||
date: NgGamesFields.date;
|
||||
winnerNation: NgGamesFields.winnerNation;
|
||||
map: NgGamesFields.map;
|
||||
season: NgGamesFields.season;
|
||||
scenario: NgGamesFields.scenario;
|
||||
scenarioName: NgGamesFields.scenarioName;
|
||||
env: NgGamesFields.env;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgHistoryFields {
|
||||
export type no = number;
|
||||
export type serverId = string;
|
||||
export type year = number | null;
|
||||
export type month = number | null;
|
||||
export type map = string | null;
|
||||
export type globalHistory = string | null;
|
||||
export type globalAction = string | null;
|
||||
export type nations = string | null;
|
||||
|
||||
}
|
||||
|
||||
export interface NgHistory {
|
||||
no: NgHistoryFields.no;
|
||||
serverId: NgHistoryFields.serverId;
|
||||
year: NgHistoryFields.year;
|
||||
month: NgHistoryFields.month;
|
||||
map: NgHistoryFields.map;
|
||||
globalHistory: NgHistoryFields.globalHistory;
|
||||
globalAction: NgHistoryFields.globalAction;
|
||||
nations: NgHistoryFields.nations;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgOldGeneralsFields {
|
||||
export type id = number;
|
||||
export type serverId = string;
|
||||
export type generalNo = number;
|
||||
export type owner = number | null;
|
||||
export type name = string;
|
||||
export type lastYearmonth = number;
|
||||
export type turntime = Date;
|
||||
export type data = string;
|
||||
|
||||
}
|
||||
|
||||
export interface NgOldGenerals {
|
||||
id: NgOldGeneralsFields.id;
|
||||
serverId: NgOldGeneralsFields.serverId;
|
||||
generalNo: NgOldGeneralsFields.generalNo;
|
||||
owner: NgOldGeneralsFields.owner;
|
||||
name: NgOldGeneralsFields.name;
|
||||
lastYearmonth: NgOldGeneralsFields.lastYearmonth;
|
||||
turntime: NgOldGeneralsFields.turntime;
|
||||
data: NgOldGeneralsFields.data;
|
||||
|
||||
}
|
||||
|
||||
export namespace NgOldNationsFields {
|
||||
export type id = number;
|
||||
export type serverId = string;
|
||||
export type nation = number;
|
||||
export type data = string;
|
||||
export type date = Date;
|
||||
|
||||
}
|
||||
|
||||
export interface NgOldNations {
|
||||
id: NgOldNationsFields.id;
|
||||
serverId: NgOldNationsFields.serverId;
|
||||
nation: NgOldNationsFields.nation;
|
||||
data: NgOldNationsFields.data;
|
||||
date: NgOldNationsFields.date;
|
||||
|
||||
}
|
||||
|
||||
export namespace PlockFields {
|
||||
export type no = number;
|
||||
export type type = EnumType;
|
||||
export type plock = number;
|
||||
export type locktime = Date;
|
||||
|
||||
}
|
||||
|
||||
export interface Plock {
|
||||
no: PlockFields.no;
|
||||
type: PlockFields.type;
|
||||
plock: PlockFields.plock;
|
||||
locktime: PlockFields.locktime;
|
||||
|
||||
}
|
||||
|
||||
export namespace RankDataFields {
|
||||
export type id = number;
|
||||
export type nationId = number;
|
||||
export type generalId = number;
|
||||
export type type = string;
|
||||
export type value = number;
|
||||
|
||||
}
|
||||
|
||||
export interface RankData {
|
||||
id: RankDataFields.id;
|
||||
nationId: RankDataFields.nationId;
|
||||
generalId: RankDataFields.generalId;
|
||||
type: RankDataFields.type;
|
||||
value: RankDataFields.value;
|
||||
|
||||
}
|
||||
|
||||
export namespace ReservedOpenFields {
|
||||
export type id = number;
|
||||
export type options = string | null;
|
||||
export type date = Date | null;
|
||||
|
||||
}
|
||||
|
||||
export interface ReservedOpen {
|
||||
id: ReservedOpenFields.id;
|
||||
options: ReservedOpenFields.options;
|
||||
date: ReservedOpenFields.date;
|
||||
|
||||
}
|
||||
|
||||
export namespace SelectNpcTokenFields {
|
||||
export type id = number;
|
||||
export type owner = number;
|
||||
export type validUntil = Date;
|
||||
export type pickMoreFrom = Date;
|
||||
export type pickResult = string;
|
||||
export type nonce = number;
|
||||
|
||||
}
|
||||
|
||||
export interface SelectNpcToken {
|
||||
id: SelectNpcTokenFields.id;
|
||||
owner: SelectNpcTokenFields.owner;
|
||||
validUntil: SelectNpcTokenFields.validUntil;
|
||||
pickMoreFrom: SelectNpcTokenFields.pickMoreFrom;
|
||||
pickResult: SelectNpcTokenFields.pickResult;
|
||||
nonce: SelectNpcTokenFields.nonce;
|
||||
|
||||
}
|
||||
|
||||
export namespace SelectPoolFields {
|
||||
export type id = number;
|
||||
export type uniqueName = string;
|
||||
export type owner = number | null;
|
||||
export type generalId = number | null;
|
||||
export type reservedUntil = Date | null;
|
||||
export type info = string;
|
||||
|
||||
}
|
||||
|
||||
export interface SelectPool {
|
||||
id: SelectPoolFields.id;
|
||||
uniqueName: SelectPoolFields.uniqueName;
|
||||
owner: SelectPoolFields.owner;
|
||||
generalId: SelectPoolFields.generalId;
|
||||
reservedUntil: SelectPoolFields.reservedUntil;
|
||||
info: SelectPoolFields.info;
|
||||
|
||||
}
|
||||
|
||||
export namespace StatisticFields {
|
||||
export type no = number;
|
||||
export type year = number | null;
|
||||
export type month = number | null;
|
||||
export type nationCount = number | null;
|
||||
export type nationName = string | null;
|
||||
export type nationHist = string | null;
|
||||
export type genCount = string | null;
|
||||
export type personalHist = string | null;
|
||||
export type specialHist = string | null;
|
||||
export type powerHist = string | null;
|
||||
export type crewtype = string | null;
|
||||
export type etc = string | null;
|
||||
export type aux = string | null;
|
||||
|
||||
}
|
||||
|
||||
export interface Statistic {
|
||||
no: StatisticFields.no;
|
||||
year: StatisticFields.year;
|
||||
month: StatisticFields.month;
|
||||
nationCount: StatisticFields.nationCount;
|
||||
nationName: StatisticFields.nationName;
|
||||
nationHist: StatisticFields.nationHist;
|
||||
genCount: StatisticFields.genCount;
|
||||
personalHist: StatisticFields.personalHist;
|
||||
specialHist: StatisticFields.specialHist;
|
||||
powerHist: StatisticFields.powerHist;
|
||||
crewtype: StatisticFields.crewtype;
|
||||
etc: StatisticFields.etc;
|
||||
aux: StatisticFields.aux;
|
||||
|
||||
}
|
||||
|
||||
export namespace StorageFields {
|
||||
export type id = number;
|
||||
export type namespace = string;
|
||||
export type key = string;
|
||||
export type value = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Storage {
|
||||
id: StorageFields.id;
|
||||
namespace: StorageFields.namespace;
|
||||
key: StorageFields.key;
|
||||
value: StorageFields.value;
|
||||
|
||||
}
|
||||
|
||||
export namespace TournamentFields {
|
||||
export type seq = number;
|
||||
export type no = number | null;
|
||||
export type npc = number | null;
|
||||
export type name = string | null;
|
||||
export type w = string | null;
|
||||
export type b = string | null;
|
||||
export type h = string | null;
|
||||
export type leadership = number | null;
|
||||
export type strength = number | null;
|
||||
export type intel = number | null;
|
||||
export type lvl = number | null;
|
||||
export type grp = number | null;
|
||||
export type grpNo = number | null;
|
||||
export type win = number | null;
|
||||
export type draw = number | null;
|
||||
export type lose = number | null;
|
||||
export type gl = number | null;
|
||||
export type prmt = number | null;
|
||||
|
||||
}
|
||||
|
||||
export interface Tournament {
|
||||
seq: TournamentFields.seq;
|
||||
no: TournamentFields.no;
|
||||
npc: TournamentFields.npc;
|
||||
name: TournamentFields.name;
|
||||
w: TournamentFields.w;
|
||||
b: TournamentFields.b;
|
||||
h: TournamentFields.h;
|
||||
leadership: TournamentFields.leadership;
|
||||
strength: TournamentFields.strength;
|
||||
intel: TournamentFields.intel;
|
||||
lvl: TournamentFields.lvl;
|
||||
grp: TournamentFields.grp;
|
||||
grpNo: TournamentFields.grpNo;
|
||||
win: TournamentFields.win;
|
||||
draw: TournamentFields.draw;
|
||||
lose: TournamentFields.lose;
|
||||
gl: TournamentFields.gl;
|
||||
prmt: TournamentFields.prmt;
|
||||
|
||||
}
|
||||
|
||||
export namespace TroopFields {
|
||||
export type troopLeader = number;
|
||||
export type nation = number;
|
||||
export type name = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Troop {
|
||||
troopLeader: TroopFields.troopLeader;
|
||||
nation: TroopFields.nation;
|
||||
name: TroopFields.name;
|
||||
|
||||
}
|
||||
|
||||
export namespace UserRecordFields {
|
||||
export type id = number;
|
||||
export type userId = number;
|
||||
export type serverId = string;
|
||||
export type logType = string;
|
||||
export type year = number;
|
||||
export type month = number;
|
||||
export type date = Date | null;
|
||||
export type text = string;
|
||||
|
||||
}
|
||||
|
||||
export interface UserRecord {
|
||||
id: UserRecordFields.id;
|
||||
userId: UserRecordFields.userId;
|
||||
serverId: UserRecordFields.serverId;
|
||||
logType: UserRecordFields.logType;
|
||||
year: UserRecordFields.year;
|
||||
month: UserRecordFields.month;
|
||||
date: UserRecordFields.date;
|
||||
text: UserRecordFields.text;
|
||||
|
||||
}
|
||||
|
||||
export namespace VoteFields {
|
||||
export type id = number;
|
||||
export type voteId = number;
|
||||
export type generalId = number;
|
||||
export type nationId = number;
|
||||
export type selection = string;
|
||||
|
||||
}
|
||||
|
||||
export interface Vote {
|
||||
id: VoteFields.id;
|
||||
voteId: VoteFields.voteId;
|
||||
generalId: VoteFields.generalId;
|
||||
nationId: VoteFields.nationId;
|
||||
selection: VoteFields.selection;
|
||||
|
||||
}
|
||||
|
||||
export namespace VoteCommentFields {
|
||||
export type id = number;
|
||||
export type voteId = number;
|
||||
export type generalId = number;
|
||||
export type nationId = number;
|
||||
export type generalName = string;
|
||||
export type nationName = string;
|
||||
export type text = string;
|
||||
export type date = Date | null;
|
||||
|
||||
}
|
||||
|
||||
export interface VoteComment {
|
||||
id: VoteCommentFields.id;
|
||||
voteId: VoteCommentFields.voteId;
|
||||
generalId: VoteCommentFields.generalId;
|
||||
nationId: VoteCommentFields.nationId;
|
||||
generalName: VoteCommentFields.generalName;
|
||||
nationName: VoteCommentFields.nationName;
|
||||
text: VoteCommentFields.text;
|
||||
date: VoteCommentFields.date;
|
||||
|
||||
}
|
||||
|
||||
export namespace WorldHistoryFields {
|
||||
export type id = number;
|
||||
export type nationId = number;
|
||||
export type year = number;
|
||||
export type month = number;
|
||||
export type text = string;
|
||||
|
||||
}
|
||||
|
||||
export interface WorldHistory {
|
||||
id: WorldHistoryFields.id;
|
||||
nationId: WorldHistoryFields.nationId;
|
||||
year: WorldHistoryFields.year;
|
||||
month: WorldHistoryFields.month;
|
||||
text: WorldHistoryFields.text;
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import 'reflect-metadata';
|
||||
import connectDB from './connectDB.js';
|
||||
import express, { type Request, type Response } from "express"
|
||||
import session from "express-session";
|
||||
import path from 'node:path';
|
||||
import { LiteHashDRBG } from './util/LiteHashDRBG.js';
|
||||
import { simpleSerialize } from './util/simpleSerialize.js';
|
||||
import { buildAPISystem } from './api/generator.js';
|
||||
import { unwrap } from './util/unwrap.js';
|
||||
import { sammoAPI } from './api/api.js';
|
||||
import { ownConfig } from './serverConfig.js';
|
||||
|
||||
connectDB.then(async (db) => {
|
||||
// create express app
|
||||
const app = express()
|
||||
app.use(express.json());
|
||||
app.use(session({
|
||||
secret: unwrap(ownConfig.sessionSecret),
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
}))
|
||||
//app.set('etag', false);
|
||||
|
||||
app.use('/api', buildAPISystem(sammoAPI));
|
||||
|
||||
// start express server
|
||||
app.listen(ownConfig.port)
|
||||
|
||||
console.log(`Express server has started on port ${ownConfig.port}`)
|
||||
|
||||
}).catch(error => console.log(error));
|
||||
|
||||
export default {};
|
||||
@@ -1,23 +0,0 @@
|
||||
import { type UserIDType } from "./User.js";
|
||||
import { Mongoose, Schema, model } from "mongoose";
|
||||
|
||||
export interface ILoginToken {
|
||||
userID: UserIDType;
|
||||
token: string;
|
||||
ip: string;
|
||||
regDate: Date;
|
||||
validUntil: Date;
|
||||
}
|
||||
|
||||
export const LoginToken = new Schema<ILoginToken>({
|
||||
userID: { type: Number, required: true },
|
||||
token: { type: String, required: true },
|
||||
ip: { type: String, required: true },
|
||||
regDate: { type: Date, required: true },
|
||||
validUntil: { type: Date, required: true },
|
||||
}, { autoIndex: false, autoCreate: false, })
|
||||
.index({ userID: 1, token: 1 })
|
||||
.index({ validUntil: 1 }, { expireAfterSeconds: 1 })
|
||||
;
|
||||
|
||||
export default (conn: Mongoose)=>conn.model<ILoginToken>('LoginToken', LoginToken);
|
||||
@@ -1,23 +0,0 @@
|
||||
import { Mongoose, Schema, model } from "mongoose";
|
||||
|
||||
export interface IServerConfig {
|
||||
allowLogin: boolean;
|
||||
allowOAuthLogin: boolean;
|
||||
allowRegister: boolean;
|
||||
};
|
||||
|
||||
export const ServerConfig = new Schema<IServerConfig>({
|
||||
allowLogin: { type: Boolean, required: true },
|
||||
allowOAuthLogin: { type: Boolean, required: true },
|
||||
allowRegister: { type: Boolean, required: true },
|
||||
}, {
|
||||
autoIndex: false,
|
||||
autoCreate: false,
|
||||
capped: {
|
||||
max: 1,
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
//단일 document로 관리
|
||||
export default (conn:Mongoose)=>conn.model<IServerConfig>('ServerConfig', ServerConfig);
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Schema, model } from "mongoose";
|
||||
|
||||
export interface IServerVersion {
|
||||
serverKey: string;
|
||||
branch: string;
|
||||
version: string;
|
||||
updateDate: Date;
|
||||
}
|
||||
|
||||
export const ServerVersion = new Schema<IServerVersion>({
|
||||
serverKey: { type: String, required: true },
|
||||
branch: { type: String, required: true },
|
||||
version: { type: String, required: true },
|
||||
updateDate: { type: Date, required: true },
|
||||
}, { autoIndex: false, autoCreate: false, })
|
||||
.index({ serverKey: 1 }, { unique: true })
|
||||
;
|
||||
|
||||
export default model<IServerVersion>('ServerVersion', ServerVersion);
|
||||
@@ -1,90 +0,0 @@
|
||||
import { Schema, model } from 'mongoose';
|
||||
|
||||
export type UserIDType = number;
|
||||
|
||||
const validOAuthTypeList = ['KAKAO', 'NONE'] as const;
|
||||
export type validOAuthType = typeof validOAuthTypeList[number];
|
||||
|
||||
const validServerActionTypeList = [
|
||||
'Update', 'UpdateByGitPath', 'ShowErrorLog',
|
||||
'CloseServer', 'OpenServer', 'StopAndResumeServer', 'OpenVote',
|
||||
] as const;
|
||||
export type ServerActionType = typeof validServerActionTypeList[number];
|
||||
|
||||
const validGatewayActionTypeList = [
|
||||
'Update', 'UpdateByGitPath', 'ShowErrorLog', 'ResetUserPassword', 'ChangeGatewayState', 'DeleteUser',
|
||||
] as const;
|
||||
|
||||
export type GatewayActionType = typeof validGatewayActionTypeList[number];
|
||||
|
||||
interface IUser {
|
||||
_id: UserIDType;
|
||||
|
||||
oauthID?: bigint;
|
||||
id: string;
|
||||
email: string;
|
||||
|
||||
oauthType: validOAuthType;
|
||||
oauthInfo?: object;
|
||||
tokenValidUntil?: Date;
|
||||
|
||||
userSalt: string;
|
||||
hashedPassword: string;
|
||||
|
||||
allowThirdPartyUse: boolean;
|
||||
|
||||
userName: string;
|
||||
allowServerAction?: Map<string, ServerActionType[]>;
|
||||
allowGatewayAction?: ServerActionType[];
|
||||
penalty?: Map<string, Date>;
|
||||
|
||||
picture?: string;
|
||||
useImgSvr?: boolean;
|
||||
|
||||
regDate: Date;
|
||||
deleteAfter?: Date;
|
||||
}
|
||||
|
||||
export const User = new Schema<IUser>({
|
||||
_id: { type: Number, required: true },
|
||||
|
||||
oauthID: { type: BigInt, required: false },
|
||||
id: { type: String, required: true },
|
||||
email: { type: String, required: true },
|
||||
|
||||
oauthType: { type: String, required: true, enum: validOAuthTypeList },
|
||||
oauthInfo: { type: Object, required: false },
|
||||
tokenValidUntil: { type: Date, required: false },
|
||||
|
||||
userSalt: { type: String, required: true },
|
||||
hashedPassword: { type: String, required: true },
|
||||
|
||||
allowThirdPartyUse: { type: Boolean, required: true },
|
||||
|
||||
userName: { type: String, required: true },
|
||||
allowServerAction: {
|
||||
type: Map, required: false, of: {
|
||||
type: Array,
|
||||
of: { type: String, enum: validServerActionTypeList }
|
||||
}
|
||||
},
|
||||
allowGatewayAction: {
|
||||
type: Array, required: false, of: {
|
||||
type: String, enum: validGatewayActionTypeList
|
||||
}
|
||||
},
|
||||
penalty: { type: Map, required: false, of: Date },
|
||||
|
||||
picture: { type: String, required: false },
|
||||
useImgSvr: { type: Boolean, required: false },
|
||||
|
||||
regDate: { type: Date, required: true },
|
||||
deleteAfter: { type: Date, required: false },
|
||||
}, { autoIndex: false, autoCreate: false })
|
||||
.index({ id: 1 }, { unique: true })
|
||||
.index({ email: 1 }, { unique: true })
|
||||
.index({ oauthID: 1 }, { unique: true, sparse: true })
|
||||
.index({ deleteAfter: 1 }) // 자동 삭제 아님!
|
||||
;
|
||||
|
||||
export default model<IUser>('User', User);
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Schema, model, } from 'mongoose';
|
||||
import { type UserIDType } from './User.js';
|
||||
|
||||
export type LogType = 'register'
|
||||
| 'login_pw' | 'login_token' | 'login_oauth' | 'logout'
|
||||
| 'change_pw' | 'reset_pw';
|
||||
const LogTypeList: LogType[] = [
|
||||
'register',
|
||||
'login_pw', 'login_token', 'login_oauth', 'logout',
|
||||
'change_pw', 'reset_pw',
|
||||
];
|
||||
|
||||
interface IUserLog {
|
||||
userID: UserIDType;
|
||||
logDate: Date;
|
||||
logType: LogType;
|
||||
action: object;
|
||||
}
|
||||
|
||||
export const UserLog = new Schema<IUserLog>({
|
||||
userID: { type: Number, required: true },
|
||||
logDate: { type: Date, required: true },
|
||||
logType: { type: String, required: true, enum: LogTypeList },
|
||||
action: { type: Object, required: true },
|
||||
}, { autoIndex: false, autoCreate: false, })
|
||||
.index({ userID: 1, logDate: 1 })
|
||||
.index({ logDate: 1 }, { expireAfterSeconds: 60 * 60 * 24 * 365 * 3 })
|
||||
;
|
||||
|
||||
export default model<IUserLog>('UserLog', UserLog);
|
||||
@@ -1,9 +0,0 @@
|
||||
import 'dotenv/config';
|
||||
import { unwrap } from './util/unwrap.js';
|
||||
|
||||
export const ownConfig = {
|
||||
sessionSecret: unwrap(process.env.SESSION_SECRET),
|
||||
port: Number(unwrap(process.env.SERVER_PORT)),
|
||||
gatewayHost: unwrap(process.env.GATEWAY_HOST),
|
||||
gatewayPort: Number(unwrap(process.env.GATEWAY_PORT)),
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
export type Entries<T> = {
|
||||
[K in keyof T]: [K, T[K]];
|
||||
}[keyof T][];
|
||||
@@ -1,586 +0,0 @@
|
||||
import { unwrap_err } from "./unwrap_err.js";
|
||||
|
||||
// https://github.com/coxcore/postposition 의 php 버전을 다시 typescript로 재 작성
|
||||
const KO_START_CODE = 44032;
|
||||
const KO_FINISH_CODE = 55203;
|
||||
const HANJA_START_CODE = 0x4e00;
|
||||
const HANJA_FINISH_CODE = 0xfa0b;
|
||||
const REG_INVALID_CHAR_W_HANJA = /[^a-zA-Z0-9ㄱ-ㅎ가-힣一-廓\s]+/u;
|
||||
const REG_INVALID_CHAR = /[^a-zA-Z0-9ㄱ-ㅎ가-힣\s]+/u;
|
||||
const REG_TARGET_CHAR = /^[\s\S]*?(\S*)\s*$/u;
|
||||
|
||||
const PRE_REG_NORMAL_FIXED = [
|
||||
"check|[hm]ook|limit",
|
||||
];
|
||||
const PRE_REG_SPECIAL_CHAR = [
|
||||
"[ㄱ-ㄷㅁ-ㅎ]",
|
||||
"^[036]",
|
||||
"[^a-zA-Z][036]",
|
||||
"[a-zA-Z]9",
|
||||
"^[mn]",
|
||||
"\\S[mn]e?",
|
||||
"\\S(?:[aeiom]|lu)b",
|
||||
"(?:u|\\S[aei]|[^o]o)p",
|
||||
"(?:^i|[^auh]i|\\Su|[^ei][ae]|[^oi]o)t",
|
||||
"(?:\\S[iou]|[^e][ae])c?k",
|
||||
"\\S[aeiou](?:c|ng)",
|
||||
"foot|go+d|b[ai]g|private",
|
||||
"^(?:app|kor)",
|
||||
];
|
||||
const PRE_REG_SPECIAL_RO = [
|
||||
"[178ㄹ]",
|
||||
"^[lr]",
|
||||
"^\\Sr",
|
||||
"\\Sle?",
|
||||
];
|
||||
|
||||
const DEFAULT_POSTPOSITION = {
|
||||
"은": "는",
|
||||
"이": "가",
|
||||
"과": "와",
|
||||
"이나": "나",
|
||||
"을": "를",
|
||||
"으로": "로",
|
||||
"이라": "라",
|
||||
"이랑": "랑",
|
||||
};
|
||||
|
||||
const JONGSUNG_HANJA = [
|
||||
0x523b, 0x5374, 0x5404, 0x606a, 0x6164, 0x6bbc, 0x73cf, 0x811a,
|
||||
0x89ba, 0x89d2, 0x95a3, 0x4f83, 0x520a, 0x58be, 0x5978, 0x59e6,
|
||||
0x5e72, 0x5e79, 0x61c7, 0x63c0, 0x6746, 0x67ec, 0x687f, 0x6f97,
|
||||
0x764e, 0x770b, 0x78f5, 0x7a08, 0x7aff, 0x7c21, 0x809d, 0x826e,
|
||||
0x8271, 0x8aeb, 0x9593, 0x4e6b, 0x559d, 0x66f7, 0x6e34, 0x78a3,
|
||||
0x7aed, 0x845b, 0x8910, 0x874e, 0x97a8, 0x52d8, 0x574e, 0x582a,
|
||||
0x5d4c, 0x611f, 0x61be, 0x6221, 0x6562, 0x67d1, 0x6a44, 0x6e1b,
|
||||
0x7518, 0x75b3, 0x76e3, 0x77b0, 0x7d3a, 0x90af, 0x9451, 0x9452,
|
||||
0x9f95, 0x5323, 0x5cac, 0x7532, 0x80db, 0x9240, 0x9598, 0x525b,
|
||||
0x5808, 0x59dc, 0x5ca1, 0x5d17, 0x5eb7, 0x5f3a, 0x5f4a, 0x6177,
|
||||
0x6c5f, 0x757a, 0x7586, 0x7ce0, 0x7d73, 0x7db1, 0x7f8c, 0x8154,
|
||||
0x8221, 0x8591, 0x8941, 0x8b1b, 0x92fc, 0x964d, 0x9c47, 0x5580,
|
||||
0x5ba2, 0x5751, 0xf901, 0x7cb3, 0x7fb9, 0x91b5, 0x4e7e, 0x4ef6,
|
||||
0x5065, 0x5dfe, 0x5efa, 0x6106, 0x6957, 0x8171, 0x8654, 0x8e47,
|
||||
0x9375, 0x9a2b, 0x4e5e, 0x5091, 0x6770, 0x6840, 0x5109, 0x528d,
|
||||
0x5292, 0x6aa2, 0x77bc, 0x9210, 0x9ed4, 0x52ab, 0x602f, 0x8ff2,
|
||||
0x64ca, 0x683c, 0x6a84, 0x6fc0, 0x8188, 0x89a1, 0x9694, 0x5805,
|
||||
0x727d, 0x72ac, 0x7504, 0x7d79, 0x7e6d, 0x80a9, 0x898b, 0x8b74,
|
||||
0x9063, 0x9d51, 0x6289, 0x6c7a, 0x6f54, 0x7d50, 0x7f3a, 0x8a23,
|
||||
0x517c, 0x614a, 0x7b9d, 0x8b19, 0x9257, 0x938c, 0x4eac, 0x4fd3,
|
||||
0x501e, 0x50be, 0x5106, 0x52c1, 0x52cd, 0x537f, 0x5770, 0x5883,
|
||||
0x5e9a, 0x5f91, 0x6176, 0x61ac, 0x64ce, 0x656c, 0x666f, 0x66bb,
|
||||
0x66f4, 0x6897, 0x6d87, 0x7085, 0x70f1, 0x749f, 0x74a5, 0x74ca,
|
||||
0x75d9, 0x786c, 0x78ec, 0x7adf, 0x7af6, 0x7d45, 0x7d93, 0x8015,
|
||||
0x803f, 0x811b, 0x8396, 0x8b66, 0x8f15, 0x9015, 0x93e1, 0x9803,
|
||||
0x9838, 0x9a5a, 0x9be8, 0x54ed, 0x659b, 0x66f2, 0x688f, 0x7a40,
|
||||
0x8c37, 0x9d60, 0x56f0, 0x5764, 0x5d11, 0x6606, 0x68b1, 0x68cd,
|
||||
0x6efe, 0x7428, 0x889e, 0x9be4, 0x6c68, 0xf904, 0x9aa8, 0x4f9b,
|
||||
0x516c, 0x5171, 0x529f, 0x5b54, 0x5de5, 0x6050, 0x606d, 0x62f1,
|
||||
0x63a7, 0x653b, 0x73d9, 0x7a7a, 0x86a3, 0x8ca2, 0x978f, 0x4e32,
|
||||
0x5ed3, 0x69e8, 0x85ff, 0x90ed, 0xf905, 0x51a0, 0x5b98, 0x5bec,
|
||||
0x6163, 0x68fa, 0x6b3e, 0x704c, 0x742f, 0x74d8, 0x7ba1, 0x7f50,
|
||||
0x83c5, 0x89c0, 0x8cab, 0x95dc, 0x9928, 0x522e, 0x605d, 0x62ec,
|
||||
0x9002, 0x4f8a, 0x5149, 0x5321, 0x58d9, 0x5ee3, 0x66e0, 0x6d38,
|
||||
0x709a, 0x72c2, 0x73d6, 0x7b50, 0x80f1, 0x945b, 0x5b8f, 0x7d18,
|
||||
0x80b1, 0x8f5f, 0x570b, 0x5c40, 0x83ca, 0x97a0, 0x97ab, 0x9eb4,
|
||||
0x541b, 0x7a98, 0x7fa4, 0x88d9, 0x8ecd, 0x90e1, 0x5800, 0x5c48,
|
||||
0x6398, 0x7a9f, 0x5bae, 0x5f13, 0x7a79, 0x7aae, 0x828e, 0x8eac,
|
||||
0x5026, 0x5238, 0x52f8, 0x5377, 0x5708, 0x62f3, 0x6372, 0x6b0a,
|
||||
0x6dc3, 0x7737, 0x53a5, 0x7357, 0x8568, 0x8e76, 0x95d5, 0x52fb,
|
||||
0x5747, 0x7547, 0x7b60, 0x83cc, 0x921e, 0xf908, 0x6a58, 0x514b,
|
||||
0x524b, 0x5287, 0x621f, 0x68d8, 0x6975, 0x9699, 0x50c5, 0x52a4,
|
||||
0x52e4, 0x61c3, 0x65a4, 0x6839, 0x69ff, 0x747e, 0x7b4b, 0x82b9,
|
||||
0x83eb, 0x89b2, 0x8b39, 0x8fd1, 0x9949, 0xf909, 0x4eca, 0x5997,
|
||||
0x64d2, 0x6611, 0x6a8e, 0x7434, 0x7981, 0x79bd, 0x82a9, 0x887e,
|
||||
0x887f, 0x895f, 0xf90a, 0x9326, 0x4f0b, 0x53ca, 0x6025, 0x6271,
|
||||
0x6c72, 0x7d1a, 0x7d66, 0x4e98, 0x5162, 0x77dc, 0x80af, 0x7dca,
|
||||
0x4f76, 0x5409, 0x62ee, 0x6854, 0x91d1, 0x55ab, 0xf914, 0xf915,
|
||||
0xf916, 0xf917, 0xf918, 0x8afe, 0xf919, 0xf91a, 0xf91b, 0xf91c,
|
||||
0x6696, 0xf91d, 0x7156, 0xf91e, 0xf91f, 0x96e3, 0xf920, 0x634f,
|
||||
0x637a, 0x5357, 0xf921, 0x678f, 0x6960, 0x6e73, 0xf922, 0x7537,
|
||||
0xf923, 0xf924, 0xf925, 0x7d0d, 0xf926, 0xf927, 0x8872, 0x56ca,
|
||||
0x5a18, 0xf928, 0xf929, 0xf92a, 0xf92b, 0xf92c, 0xf92e, 0x5e74,
|
||||
0x649a, 0x79ca, 0x5ff5, 0x606c, 0x62c8, 0x637b, 0x5be7, 0x5bd7,
|
||||
0xf93b, 0xf93c, 0xf93d, 0xf93e, 0xf93f, 0xf940, 0xf941, 0xf942,
|
||||
0xf943, 0x6fc3, 0xf944, 0xf945, 0x81bf, 0x8fb2, 0x5ae9, 0x8a25,
|
||||
0xf952, 0xf953, 0xf954, 0xf955, 0xf956, 0xf957, 0x80fd, 0xf958,
|
||||
0xf959, 0x533f, 0x6eba, 0x4e39, 0x4eb6, 0x4f46, 0x55ae, 0x5718,
|
||||
0x58c7, 0x5f56, 0x65b7, 0x65e6, 0x6a80, 0x6bb5, 0x6e4d, 0x77ed,
|
||||
0x7aef, 0x7c1e, 0x7dde, 0x86cb, 0x8892, 0x9132, 0x935b, 0x64bb,
|
||||
0x6fbe, 0x737a, 0x75b8, 0x9054, 0x5556, 0x574d, 0x61ba, 0x64d4,
|
||||
0x66c7, 0x6de1, 0x6e5b, 0x6f6d, 0x6fb9, 0x75f0, 0x8043, 0x81bd,
|
||||
0x8541, 0x8983, 0x8ac7, 0x8b5a, 0x931f, 0x6c93, 0x7553, 0x7b54,
|
||||
0x8e0f, 0x905d, 0x5510, 0x5802, 0x5858, 0x5e62, 0x6207, 0x649e,
|
||||
0x68e0, 0x7576, 0x7cd6, 0x87b3, 0x9ee8, 0x5b85, 0x5fb7, 0x60b3,
|
||||
0x6bd2, 0x7006, 0x7258, 0x72a2, 0x7368, 0x7763, 0x79bf, 0x7be4,
|
||||
0x7e9b, 0x8b80, 0x58a9, 0x60c7, 0x6566, 0x65fd, 0x66be, 0x6c8c,
|
||||
0x711e, 0x71c9, 0x8c5a, 0x9813, 0x4e6d, 0x7a81, 0x4edd, 0x51ac,
|
||||
0x51cd, 0x52d5, 0x540c, 0x61a7, 0x6771, 0x6850, 0x68df, 0x6d1e,
|
||||
0x6f7c, 0x75bc, 0x77b3, 0x7ae5, 0x80f4, 0x8463, 0x9285, 0x5c6f,
|
||||
0x81c0, 0x829a, 0x9041, 0x906f, 0x920d, 0x5f97, 0x5d9d, 0x6a59,
|
||||
0x71c8, 0x767b, 0x7b49, 0x85e4, 0x8b04, 0x9127, 0x9a30, 0xf95c,
|
||||
0x6d1b, 0x70d9, 0x73de, 0x7d61, 0x843d, 0xf95d, 0x916a, 0x99f1,
|
||||
0xf95e, 0x4e82, 0x5375, 0x6b04, 0x6b12, 0x703e, 0x721b, 0x862d,
|
||||
0x9e1e, 0x524c, 0x8fa3, 0x5d50, 0x64e5, 0x652c, 0x6b16, 0x6feb,
|
||||
0x7c43, 0x7e9c, 0x85cd, 0x8964, 0x89bd, 0x62c9, 0x81d8, 0x881f,
|
||||
0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x7405, 0x746f, 0x8782, 0x90de,
|
||||
0x51b7, 0x63a0, 0x7565, 0x4eae, 0x5006, 0x5169, 0x51c9, 0x6881,
|
||||
0x6a11, 0x7cae, 0x7cb1, 0x7ce7, 0x826f, 0x8ad2, 0x8f1b, 0x91cf,
|
||||
0x529b, 0x66c6, 0x6b77, 0x701d, 0x792b, 0x8f62, 0x9742, 0x6190,
|
||||
0x6200, 0x6523, 0x6f23, 0x7149, 0x7489, 0x7df4, 0x806f, 0x84ee,
|
||||
0x8f26, 0x9023, 0x934a, 0x51bd, 0x5217, 0x52a3, 0x6d0c, 0x70c8,
|
||||
0x88c2, 0x5ec9, 0x6582, 0x6bae, 0x6fc2, 0x7c3e, 0x7375, 0x4ee4,
|
||||
0x4f36, 0x56f9, 0xf95f, 0x5cba, 0x5dba, 0x601c, 0x73b2, 0x7b2d,
|
||||
0x7f9a, 0x7fce, 0x8046, 0x901e, 0x9234, 0x96f6, 0x9748, 0x9818,
|
||||
0x9f61, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304, 0x9e7f, 0x9e93,
|
||||
0x8ad6, 0x58df, 0x5f04, 0x6727, 0x7027, 0x74cf, 0x7c60, 0x807e,
|
||||
0x9f8d, 0x516d, 0x622e, 0x9678, 0x4f96, 0x502b, 0x5d19, 0x6dea,
|
||||
0x7db8, 0x8f2a, 0x5f8b, 0x6144, 0x6817, 0xf961, 0x9686, 0x52d2,
|
||||
0x808b, 0x51dc, 0x51cc, 0x695e, 0x7a1c, 0x7dbe, 0x83f1, 0x9675,
|
||||
0x541d, 0x6f7e, 0x71d0, 0x7498, 0x85fa, 0x8eaa, 0x96a3, 0x9c57,
|
||||
0x9e9f, 0x6797, 0x6dcb, 0x7433, 0x81e8, 0x9716, 0x782c, 0x7acb,
|
||||
0x7b20, 0x7c92, 0x5bde, 0x5e55, 0x6f20, 0x819c, 0x83ab, 0x9088,
|
||||
0x4e07, 0x534d, 0x5a29, 0x5dd2, 0x5f4e, 0x6162, 0x633d, 0x6669,
|
||||
0x66fc, 0x6eff, 0x6f2b, 0x7063, 0x779e, 0x842c, 0x8513, 0x883b,
|
||||
0x8f13, 0x9945, 0x9c3b, 0x551c, 0x62b9, 0x672b, 0x6cab, 0x8309,
|
||||
0x896a, 0x977a, 0x4ea1, 0x5984, 0x5fd8, 0x5fd9, 0x671b, 0x7db2,
|
||||
0x7f54, 0x8292, 0x832b, 0x83bd, 0x8f1e, 0x9099, 0x8108, 0x8c8a,
|
||||
0x964c, 0x9a40, 0x9ea5, 0x5b5f, 0x6c13, 0x731b, 0x76f2, 0x76df,
|
||||
0x840c, 0x51aa, 0x8993, 0x514d, 0x5195, 0x52c9, 0x68c9, 0x6c94,
|
||||
0x7704, 0x7720, 0x7dbf, 0x7dec, 0x9762, 0x9eb5, 0x6ec5, 0x8511,
|
||||
0x51a5, 0x540d, 0x547d, 0x660e, 0x669d, 0x6927, 0x6e9f, 0x76bf,
|
||||
0x7791, 0x8317, 0x84c2, 0x879f, 0x9169, 0x9298, 0x9cf4, 0x6728,
|
||||
0x6c90, 0x7267, 0x76ee, 0x7766, 0x7a46, 0x9da9, 0x6b7f, 0x6c92,
|
||||
0x5922, 0x6726, 0x8499, 0x58a8, 0x9ed8, 0x5011, 0x520e, 0x543b,
|
||||
0x554f, 0x6587, 0x6c76, 0x7d0a, 0x7d0b, 0x805e, 0x868a, 0x9580,
|
||||
0x96ef, 0x52ff, 0x6c95, 0x7269, 0x5cb7, 0x60b6, 0x610d, 0x61ab,
|
||||
0x654f, 0x65fb, 0x65fc, 0x6c11, 0x6cef, 0x739f, 0x73c9, 0x7de1,
|
||||
0x9594, 0x5bc6, 0x871c, 0x8b10, 0x525d, 0x535a, 0x62cd, 0x640f,
|
||||
0x64b2, 0x6734, 0x6a38, 0x6cca, 0x73c0, 0x749e, 0x7b94, 0x7c95,
|
||||
0x7e1b, 0x818a, 0x8236, 0x8584, 0x8feb, 0x96f9, 0x99c1, 0x4f34,
|
||||
0x534a, 0x53cd, 0x53db, 0x62cc, 0x642c, 0x6500, 0x6591, 0x69c3,
|
||||
0x6cee, 0x6f58, 0x73ed, 0x7554, 0x7622, 0x76e4, 0x76fc, 0x78d0,
|
||||
0x78fb, 0x792c, 0x7d46, 0x822c, 0x87e0, 0x8fd4, 0x9812, 0x98ef,
|
||||
0x52c3, 0x62d4, 0x64a5, 0x6e24, 0x6f51, 0x767c, 0x8dcb, 0x91b1,
|
||||
0x9262, 0x9aee, 0x9b43, 0x5023, 0x508d, 0x574a, 0x59a8, 0x5c28,
|
||||
0x5e47, 0x5f77, 0x623f, 0x653e, 0x65b9, 0x65c1, 0x6609, 0x678b,
|
||||
0x699c, 0x6ec2, 0x78c5, 0x7d21, 0x80aa, 0x8180, 0x822b, 0x82b3,
|
||||
0x84a1, 0x868c, 0x8a2a, 0x8b17, 0x90a6, 0x9632, 0x9f90, 0x4f2f,
|
||||
0x4f70, 0x5e1b, 0x67cf, 0x6822, 0x767d, 0x767e, 0x9b44, 0x5e61,
|
||||
0x6a0a, 0x7169, 0x71d4, 0x756a, 0xf964, 0x7e41, 0x8543, 0x85e9,
|
||||
0x98dc, 0x4f10, 0x7b4f, 0x7f70, 0x95a5, 0x51e1, 0x5e06, 0x68b5,
|
||||
0x6c3e, 0x6c4e, 0x6cdb, 0x72af, 0x7bc4, 0x8303, 0x6cd5, 0x743a,
|
||||
0x50fb, 0x5288, 0x58c1, 0x64d8, 0x6a97, 0x74a7, 0x7656, 0x78a7,
|
||||
0x8617, 0x95e2, 0x9739, 0xf965, 0x535e, 0x5f01, 0x8b8a, 0x8fa8,
|
||||
0x8faf, 0x908a, 0x5225, 0x77a5, 0x9c49, 0x9f08, 0x4e19, 0x5002,
|
||||
0x5175, 0x5c5b, 0x5e77, 0x661e, 0x663a, 0x67c4, 0x68c5, 0x70b3,
|
||||
0x7501, 0x75c5, 0x79c9, 0x7add, 0x8f27, 0x9920, 0x9a08, 0x4f0f,
|
||||
0x50d5, 0x5310, 0x535c, 0x5b93, 0x5fa9, 0x670d, 0x798f, 0x8179,
|
||||
0x832f, 0x8514, 0x8907, 0x8986, 0x8f39, 0x8f3b, 0x99a5, 0x9c12,
|
||||
0x672c, 0x4e76, 0x4ff8, 0x5949, 0x5c01, 0x5cef, 0x5cf0, 0x6367,
|
||||
0x68d2, 0x70fd, 0x71a2, 0x742b, 0x7e2b, 0x84ec, 0x8702, 0x9022,
|
||||
0x92d2, 0x9cf3, 0x5317, 0x5206, 0x5429, 0x5674, 0x58b3, 0x5954,
|
||||
0x596e, 0x5fff, 0x61a4, 0x626e, 0x6610, 0x6c7e, 0x711a, 0x76c6,
|
||||
0x7c89, 0x7cde, 0x7d1b, 0x82ac, 0x8cc1, 0x96f0, 0xf967, 0x4f5b,
|
||||
0x5f17, 0x5f7f, 0x62c2, 0x5d29, 0x670b, 0x68da, 0x787c, 0x7e43,
|
||||
0x9d6c, 0x56ac, 0x5b2a, 0x5f6c, 0x658c, 0x6ab3, 0x6baf, 0x6d5c,
|
||||
0x6ff1, 0x7015, 0x725d, 0x73ad, 0x8ca7, 0x8cd3, 0x983b, 0x6191,
|
||||
0x6c37, 0x8058, 0x9a01, 0x524a, 0xf969, 0x6714, 0xf96a, 0x5098,
|
||||
0x522a, 0x5c71, 0x6563, 0x6c55, 0x73ca, 0x7523, 0x759d, 0x7b97,
|
||||
0x849c, 0x9178, 0x9730, 0x4e77, 0x6492, 0x6bba, 0x715e, 0x85a9,
|
||||
0x4e09, 0xf96b, 0x6749, 0x68ee, 0x6e17, 0x829f, 0x8518, 0x886b,
|
||||
0x63f7, 0x6f81, 0x9212, 0x98af, 0x4e0a, 0x50b7, 0x50cf, 0x511f,
|
||||
0x5546, 0x55aa, 0x5617, 0x5b40, 0x5c19, 0x5ce0, 0x5e38, 0x5e8a,
|
||||
0x5ea0, 0x5ec2, 0x60f3, 0x6851, 0x6a61, 0x6e58, 0x723d, 0x7240,
|
||||
0x72c0, 0x76f8, 0x7965, 0x7bb1, 0x7fd4, 0x88f3, 0x89f4, 0x8a73,
|
||||
0x8c61, 0x8cde, 0x971c, 0x55c7, 0xf96c, 0x7a61, 0x7d22, 0x8272,
|
||||
0x7272, 0x751f, 0x7525, 0xf96d, 0x7b19, 0x5915, 0x596d, 0x5e2d,
|
||||
0x60dc, 0x6614, 0x6673, 0x6790, 0x6c50, 0x6dc5, 0x6f5f, 0x77f3,
|
||||
0x78a9, 0x84c6, 0x91cb, 0x932b, 0x4ed9, 0x50ca, 0x5148, 0x5584,
|
||||
0x5b0b, 0x5ba3, 0x6247, 0x657e, 0x65cb, 0x6e32, 0x717d, 0x7401,
|
||||
0x7444, 0x7487, 0x74bf, 0x766c, 0x79aa, 0x7dda, 0x7e55, 0x7fa8,
|
||||
0x817a, 0x81b3, 0x8239, 0x861a, 0x87ec, 0x8a75, 0x8de3, 0x9078,
|
||||
0x9291, 0x9425, 0x994d, 0x9bae, 0x5368, 0x5c51, 0x6954, 0x6cc4,
|
||||
0x6d29, 0x6e2b, 0x820c, 0x859b, 0x893b, 0x8a2d, 0x8aaa, 0x96ea,
|
||||
0x9f67, 0x5261, 0x66b9, 0x6bb2, 0x7e96, 0x87fe, 0x8d0d, 0x9583,
|
||||
0x965d, 0x651d, 0x6d89, 0x71ee, 0xf96e, 0x57ce, 0x59d3, 0x5bac,
|
||||
0x6027, 0x60fa, 0x6210, 0x661f, 0x665f, 0x7329, 0x73f9, 0x76db,
|
||||
0x7701, 0x7b6c, 0x8056, 0x8072, 0x8165, 0x8aa0, 0x9192, 0x4fd7,
|
||||
0x5c6c, 0x675f, 0x6d91, 0x7c9f, 0x7e8c, 0x8b16, 0x8d16, 0x901f,
|
||||
0x5b6b, 0x5dfd, 0x640d, 0x84c0, 0x905c, 0x98e1, 0x7387, 0x5b8b,
|
||||
0x609a, 0x677e, 0x6dde, 0x8a1f, 0x8aa6, 0x9001, 0x980c, 0x53d4,
|
||||
0x587e, 0x5919, 0x5b70, 0x5bbf, 0x6dd1, 0x6f5a, 0x719f, 0x7421,
|
||||
0x74b9, 0x8085, 0x83fd, 0x5de1, 0x5f87, 0x5faa, 0x6042, 0x65ec,
|
||||
0x6812, 0x696f, 0x6a53, 0x6b89, 0x6d35, 0x6df3, 0x73e3, 0x76fe,
|
||||
0x77ac, 0x7b4d, 0x7d14, 0x8123, 0x821c, 0x8340, 0x84f4, 0x8563,
|
||||
0x8a62, 0x8ac4, 0x9187, 0x931e, 0x9806, 0x99b4, 0x620c, 0x8853,
|
||||
0x8ff0, 0x9265, 0x5d07, 0x5d27, 0x5d69, 0x745f, 0x819d, 0x8768,
|
||||
0x6fd5, 0x62fe, 0x7fd2, 0x8936, 0x8972, 0x4e1e, 0x4e58, 0x50e7,
|
||||
0x52dd, 0x5347, 0x627f, 0x6607, 0x7e69, 0x8805, 0x965e, 0x57f4,
|
||||
0x5bd4, 0x5f0f, 0x606f, 0x62ed, 0x690d, 0x6b96, 0x6e5c, 0x7184,
|
||||
0x7bd2, 0x8755, 0x8b58, 0x8efe, 0x98df, 0x98fe, 0x4f38, 0x4f81,
|
||||
0x4fe1, 0x547b, 0x5a20, 0x5bb8, 0x613c, 0x65b0, 0x6668, 0x71fc,
|
||||
0x7533, 0x795e, 0x7d33, 0x814e, 0x81e3, 0x8398, 0x85aa, 0x85ce,
|
||||
0x8703, 0x8a0a, 0x8eab, 0x8f9b, 0xf971, 0x8fc5, 0x5931, 0x5ba4,
|
||||
0x5be6, 0x6089, 0x5be9, 0x5c0b, 0x5fc3, 0x6c81, 0xf972, 0x6df1,
|
||||
0x700b, 0x751a, 0x82af, 0x8af6, 0x4ec0, 0x5341, 0xf973, 0x96d9,
|
||||
0x580a, 0x5cb3, 0x5dbd, 0x5e44, 0x60e1, 0x6115, 0x63e1, 0x6a02,
|
||||
0x6e25, 0x9102, 0x9354, 0x984e, 0x9c10, 0x9f77, 0x5b89, 0x5cb8,
|
||||
0x6309, 0x664f, 0x6848, 0x773c, 0x96c1, 0x978d, 0x9854, 0x9b9f,
|
||||
0x65a1, 0x8b01, 0x8ecb, 0x95bc, 0x5535, 0x5ca9, 0x5dd6, 0x5eb5,
|
||||
0x6697, 0x764c, 0x83f4, 0x95c7, 0x58d3, 0x62bc, 0x72ce, 0x9d28,
|
||||
0x4ef0, 0x592e, 0x600f, 0x663b, 0x6b83, 0x79e7, 0x9d26, 0x5384,
|
||||
0x627c, 0x6396, 0x6db2, 0x7e0a, 0x814b, 0x984d, 0x6afb, 0x7f4c,
|
||||
0x9daf, 0x9e1a, 0x5f31, 0xf975, 0xf976, 0x7d04, 0x82e5, 0x846f,
|
||||
0x84bb, 0x85e5, 0x8e8d, 0xf977, 0x4f6f, 0xf978, 0xf979, 0x58e4,
|
||||
0x5b43, 0x6059, 0x63da, 0x6518, 0x656d, 0x6698, 0xf97a, 0x694a,
|
||||
0x6a23, 0x6d0b, 0x7001, 0x716c, 0x75d2, 0x760d, 0x79b3, 0x7a70,
|
||||
0xf97b, 0x7f8a, 0xf97c, 0x8944, 0xf97d, 0x8b93, 0x91c0, 0x967d,
|
||||
0xf97e, 0x990a, 0x5104, 0x61b6, 0x6291, 0x6a8d, 0x81c6, 0x5043,
|
||||
0x5830, 0x5f66, 0x7109, 0x8a00, 0x8afa, 0x5b7c, 0x8616, 0x4ffa,
|
||||
0x513c, 0x56b4, 0x5944, 0x63a9, 0x6df9, 0x5daa, 0x696d, 0x5186,
|
||||
0x4ea6, 0xf98a, 0x57df, 0x5f79, 0x6613, 0xf98b, 0xf98c, 0x75ab,
|
||||
0x7e79, 0x8b6f, 0xf98d, 0x9006, 0x9a5b, 0x56a5, 0x5827, 0x59f8,
|
||||
0x5a1f, 0x5bb4, 0xf98e, 0x5ef6, 0xf98f, 0xf990, 0x6350, 0x633b,
|
||||
0xf991, 0x693d, 0x6c87, 0x6cbf, 0x6d8e, 0x6d93, 0x6df5, 0x6f14,
|
||||
0xf992, 0x70df, 0x7136, 0x7159, 0xf993, 0x71c3, 0x71d5, 0xf994,
|
||||
0x784f, 0x786f, 0xf995, 0x7b75, 0x7de3, 0xf996, 0x7e2f, 0xf997,
|
||||
0x884d, 0x8edf, 0xf998, 0xf999, 0xf99a, 0x925b, 0xf99b, 0x9cf6,
|
||||
0xf99c, 0xf99d, 0xf99e, 0x6085, 0x6d85, 0xf99f, 0x71b1, 0xf9a0,
|
||||
0xf9a1, 0x95b1, 0x53ad, 0xf9a2, 0xf9a3, 0xf9a4, 0x67d3, 0xf9a5,
|
||||
0x708e, 0x7130, 0x7430, 0x8276, 0x82d2, 0xf9a6, 0x95bb, 0x9ae5,
|
||||
0x9e7d, 0x66c4, 0xf9a7, 0x71c1, 0x8449, 0xf9a8, 0xf9a9, 0x584b,
|
||||
0xf9aa, 0xf9ab, 0x5db8, 0x5f71, 0xf9ac, 0x6620, 0x668e, 0x6979,
|
||||
0x69ae, 0x6c38, 0x6cf3, 0x6e36, 0x6f41, 0x6fda, 0x701b, 0x702f,
|
||||
0x7150, 0x71df, 0x7370, 0xf9ad, 0x745b, 0xf9ae, 0x74d4, 0x76c8,
|
||||
0x7a4e, 0x7e93, 0xf9af, 0xf9b0, 0x82f1, 0x8a60, 0x8fce, 0xf9b1,
|
||||
0x9348, 0xf9b2, 0x9719, 0xf9b3, 0xf9b4, 0x5c4b, 0x6c83, 0x7344,
|
||||
0x7389, 0x923a, 0x6eab, 0x7465, 0x761f, 0x7a69, 0x7e15, 0x860a,
|
||||
0x5140, 0x58c5, 0x64c1, 0x74ee, 0x7515, 0x7670, 0x7fc1, 0x9095,
|
||||
0x96cd, 0x9954, 0x5a49, 0x5b8c, 0x5b9b, 0x68a1, 0x6900, 0x6d63,
|
||||
0x73a9, 0x7413, 0x742c, 0x7897, 0x7de9, 0x7feb, 0x8118, 0x8155,
|
||||
0x839e, 0x8c4c, 0x962e, 0x9811, 0x66f0, 0x5f80, 0x65fa, 0x6789,
|
||||
0x6c6a, 0x738b, 0x617e, 0x6b32, 0x6d74, 0x7e1f, 0x8925, 0x8fb1,
|
||||
0x4fd1, 0x50ad, 0x5197, 0x52c7, 0x57c7, 0x5889, 0x5bb9, 0x5eb8,
|
||||
0x6142, 0x6995, 0x6d8c, 0x6e67, 0x6eb6, 0x7194, 0x7462, 0x7528,
|
||||
0x752c, 0x8073, 0x8338, 0x84c9, 0x8e0a, 0x9394, 0x93de, 0xf9c4,
|
||||
0x52d6, 0x5f67, 0x65ed, 0x6631, 0x682f, 0x715c, 0x7a36, 0x90c1,
|
||||
0x980a, 0x4e91, 0xf9c5, 0x6a52, 0x6b9e, 0x6f90, 0x7189, 0x8018,
|
||||
0x82b8, 0x8553, 0x904b, 0x9695, 0x96f2, 0x97fb, 0x851a, 0x9b31,
|
||||
0x4e90, 0x718a, 0x96c4, 0x5143, 0x539f, 0x54e1, 0x5713, 0x5712,
|
||||
0x57a3, 0x5a9b, 0x5ac4, 0x5bc3, 0x6028, 0x613f, 0x63f4, 0x6c85,
|
||||
0x6d39, 0x6e72, 0x6e90, 0x7230, 0x733f, 0x7457, 0x82d1, 0x8881,
|
||||
0x8f45, 0x9060, 0xf9c6, 0x9662, 0x9858, 0x9d1b, 0x6708, 0x8d8a,
|
||||
0x925e, 0xf9d1, 0x5809, 0xf9d2, 0x6bd3, 0x8089, 0x80b2, 0xf9d3,
|
||||
0xf9d4, 0x5141, 0x596b, 0x5c39, 0xf9d5, 0xf9d6, 0x6f64, 0x73a7,
|
||||
0x80e4, 0x8d07, 0xf9d7, 0x9217, 0x958f, 0xf9d8, 0xf9d9, 0xf9da,
|
||||
0xf9db, 0x807f, 0x620e, 0x701c, 0x7d68, 0x878d, 0xf9dc, 0x57a0,
|
||||
0x6069, 0x6147, 0x6bb7, 0x8abe, 0x9280, 0x96b1, 0x4e59, 0x541f,
|
||||
0x6deb, 0x852d, 0x9670, 0x97f3, 0x98ee, 0x63d6, 0x6ce3, 0x9091,
|
||||
0x51dd, 0x61c9, 0x81ba, 0x9df9, 0xf9eb, 0xf9ec, 0x7037, 0x76ca,
|
||||
0x7fca, 0x7fcc, 0x7ffc, 0x8b1a, 0x4eba, 0x4ec1, 0x5203, 0x5370,
|
||||
0xf9ed, 0x54bd, 0x56e0, 0x59fb, 0x5bc5, 0x5f15, 0x5fcd, 0x6e6e,
|
||||
0xf9ee, 0xf9ef, 0x7d6a, 0x8335, 0xf9f0, 0x8693, 0x8a8d, 0xf9f1,
|
||||
0x976d, 0x9777, 0xf9f2, 0xf9f3, 0x4e00, 0x4f5a, 0x4f7e, 0x58f9,
|
||||
0x65e5, 0x6ea2, 0x9038, 0x93b0, 0x99b9, 0x4efb, 0x58ec, 0x598a,
|
||||
0x59d9, 0x6041, 0xf9f4, 0xf9f5, 0x7a14, 0xf9f6, 0x834f, 0x8cc3,
|
||||
0x5165, 0x5344, 0xf9f7, 0xf9f8, 0xf9f9, 0x4ecd, 0x5269, 0x5b55,
|
||||
0x82bf, 0x4f5c, 0x52fa, 0x56bc, 0x65ab, 0x6628, 0x707c, 0x70b8,
|
||||
0x7235, 0x7dbd, 0x828d, 0x914c, 0x96c0, 0x9d72, 0x5b71, 0x68e7,
|
||||
0x6b98, 0x6f7a, 0x76de, 0x5c91, 0x66ab, 0x6f5b, 0x7bb4, 0x7c2a,
|
||||
0x8836, 0x96dc, 0x4e08, 0x4ed7, 0x5320, 0x5834, 0x58bb, 0x58ef,
|
||||
0x596c, 0x5c07, 0x5e33, 0x5e84, 0x5f35, 0x638c, 0x66b2, 0x6756,
|
||||
0x6a1f, 0x6aa3, 0x6b0c, 0x6f3f, 0x7246, 0xf9fa, 0x7350, 0x748b,
|
||||
0x7ae0, 0x7ca7, 0x8178, 0x81df, 0x81e7, 0x838a, 0x846c, 0x8523,
|
||||
0x8594, 0x85cf, 0x88dd, 0x8d13, 0x91ac, 0x9577, 0x969c, 0x722d,
|
||||
0x7b8f, 0x8acd, 0x931a, 0x52e3, 0x540a, 0x5ae1, 0x5bc2, 0x6458,
|
||||
0x6575, 0x6ef4, 0x72c4, 0xf9fb, 0x7684, 0x7a4d, 0x7b1b, 0x7c4d,
|
||||
0x7e3e, 0x7fdf, 0x837b, 0x8b2b, 0x8cca, 0x8d64, 0x8de1, 0x8e5f,
|
||||
0x8fea, 0x8ff9, 0x9069, 0x93d1, 0x4f43, 0x4f7a, 0x50b3, 0x5168,
|
||||
0x5178, 0x524d, 0x526a, 0x5861, 0x587c, 0x5960, 0x5c08, 0x5c55,
|
||||
0x5edb, 0x609b, 0x6230, 0x6813, 0x6bbf, 0x6c08, 0x6fb1, 0x714e,
|
||||
0x7420, 0x7530, 0x7538, 0x7551, 0x7672, 0x7b4c, 0x7b8b, 0x7bad,
|
||||
0x7bc6, 0x7e8f, 0x8a6e, 0x8f3e, 0x8f49, 0x923f, 0x9293, 0x9322,
|
||||
0x942b, 0x96fb, 0x985a, 0x986b, 0x991e, 0x5207, 0x622a, 0x6298,
|
||||
0x6d59, 0x7664, 0x7aca, 0x7bc0, 0x7d76, 0x5360, 0x5cbe, 0x5e97,
|
||||
0x6f38, 0x70b9, 0x7c98, 0x9711, 0x9b8e, 0x9ede, 0x63a5, 0x647a,
|
||||
0x8776, 0x4e01, 0x4e95, 0x4ead, 0x505c, 0x5075, 0x5448, 0x59c3,
|
||||
0x5b9a, 0x5e40, 0x5ead, 0x5ef7, 0x5f81, 0x60c5, 0x633a, 0x653f,
|
||||
0x6574, 0x65cc, 0x6676, 0x6678, 0x67fe, 0x6968, 0x6a89, 0x6b63,
|
||||
0x6c40, 0x6dc0, 0x6de8, 0x6e1f, 0x6e5e, 0x701e, 0x70a1, 0x738e,
|
||||
0x73fd, 0x753a, 0x775b, 0x7887, 0x798e, 0x7a0b, 0x7a7d, 0x7cbe,
|
||||
0x7d8e, 0x8247, 0x8a02, 0x8aea, 0x8c9e, 0x912d, 0x914a, 0x91d8,
|
||||
0x9266, 0x92cc, 0x9320, 0x9706, 0x9756, 0x975c, 0x9802, 0x9f0e,
|
||||
0x65cf, 0x7c07, 0x8db3, 0x93c3, 0x5b58, 0x5c0a, 0x5352, 0x62d9,
|
||||
0x731d, 0x5027, 0x5b97, 0x5f9e, 0x60b0, 0x616b, 0x68d5, 0x6dd9,
|
||||
0x742e, 0x7a2e, 0x7d42, 0x7d9c, 0x7e31, 0x816b, 0x8e2a, 0x8e35,
|
||||
0x937e, 0x9418, 0x7af9, 0x7ca5, 0x4fca, 0x5101, 0x51c6, 0x57c8,
|
||||
0x5bef, 0x5cfb, 0x6659, 0x6a3d, 0x6d5a, 0x6e96, 0x6fec, 0x710c,
|
||||
0x756f, 0x7ae3, 0x8822, 0x9021, 0x9075, 0x96cb, 0x99ff, 0x8301,
|
||||
0x4e2d, 0x4ef2, 0x8846, 0x91cd, 0x537d, 0x6adb, 0x696b, 0x6c41,
|
||||
0x847a, 0x589e, 0x618e, 0x66fe, 0x62ef, 0x70dd, 0x7511, 0x75c7,
|
||||
0x7e52, 0x84b8, 0x8b49, 0x8d08, 0x76f4, 0x7a19, 0x7a37, 0x7e54,
|
||||
0x8077, 0x5507, 0x55d4, 0x5875, 0x632f, 0x6422, 0x6649, 0x664b,
|
||||
0x686d, 0x699b, 0x6b84, 0x6d25, 0x6eb1, 0x73cd, 0x7468, 0x74a1,
|
||||
0x755b, 0x75b9, 0x76e1, 0x771e, 0x778b, 0x79e6, 0x7e09, 0x7e1d,
|
||||
0x81fb, 0x852f, 0x8897, 0x8a3a, 0x8cd1, 0x8eeb, 0x8fb0, 0x9032,
|
||||
0x93ad, 0x9663, 0x9673, 0x9707, 0x4f84, 0x53f1, 0x59ea, 0x5ac9,
|
||||
0x5e19, 0x684e, 0x74c6, 0x75be, 0x79e9, 0x7a92, 0x81a3, 0x86ed,
|
||||
0x8cea, 0x8dcc, 0x8fed, 0x659f, 0x6715, 0xf9fd, 0x57f7, 0x6f57,
|
||||
0x7ddd, 0x8f2f, 0x93f6, 0x96c6, 0x5fb5, 0x61f2, 0x6f84, 0x6349,
|
||||
0x643e, 0x7740, 0x7a84, 0x932f, 0x947f, 0x9f6a, 0x64b0, 0x6faf,
|
||||
0x71e6, 0x74a8, 0x74da, 0x7ac4, 0x7c12, 0x7e82, 0x7cb2, 0x7e98,
|
||||
0x8b9a, 0x8d0a, 0x947d, 0x9910, 0x994c, 0x5239, 0x5bdf, 0x64e6,
|
||||
0x672d, 0x7d2e, 0x50ed, 0x53c3, 0x5879, 0x6158, 0x6159, 0x61fa,
|
||||
0x65ac, 0x7ad9, 0x8b92, 0x8b96, 0x5009, 0x5021, 0x5275, 0x5531,
|
||||
0x5a3c, 0x5ee0, 0x5f70, 0x6134, 0x655e, 0x660c, 0x6636, 0x66a2,
|
||||
0x69cd, 0x6ec4, 0x6f32, 0x7316, 0x7621, 0x7a93, 0x8139, 0x8259,
|
||||
0x83d6, 0x84bc, 0x518a, 0x67f5, 0x7b56, 0x8cac, 0x501c, 0xf9ff,
|
||||
0x5254, 0x5c3a, 0x617d, 0x621a, 0x62d3, 0x64f2, 0x65a5, 0x6ecc,
|
||||
0x7620, 0x810a, 0x8e60, 0x965f, 0x96bb, 0x4edf, 0x5343, 0x5598,
|
||||
0x5929, 0x5ddd, 0x64c5, 0x6cc9, 0x6dfa, 0x7394, 0x7a7f, 0x821b,
|
||||
0x85a6, 0x8ce4, 0x8e10, 0x9077, 0x91e7, 0x95e1, 0x9621, 0x97c6,
|
||||
0x51f8, 0x54f2, 0x5586, 0x5fb9, 0x64a4, 0x6f88, 0x7db4, 0x8f1f,
|
||||
0x8f4d, 0x9435, 0x50c9, 0x5c16, 0x6cbe, 0x6dfb, 0x751b, 0x77bb,
|
||||
0x7c3d, 0x7c64, 0x8a79, 0x8ac2, 0x581e, 0x59be, 0x5e16, 0x6377,
|
||||
0x7252, 0x758a, 0x776b, 0x8adc, 0x8cbc, 0x8f12, 0x5ef3, 0x6674,
|
||||
0x6df8, 0x807d, 0x83c1, 0x8acb, 0x9751, 0x9bd6, 0x4fc3, 0x56d1,
|
||||
0x71ed, 0x77d7, 0x8700, 0x89f8, 0x5bf8, 0x5fd6, 0x6751, 0x90a8,
|
||||
0x53e2, 0x585a, 0x5bf5, 0x60a4, 0x6181, 0x6460, 0x7e3d, 0x8070,
|
||||
0x8525, 0x9283, 0x64ae, 0x4e11, 0x755c, 0x795d, 0x7afa, 0x7b51,
|
||||
0x7bc9, 0x7e2e, 0x84c4, 0x8e59, 0x8e74, 0x8ef8, 0x9010, 0x6625,
|
||||
0x693f, 0x7443, 0x51fa, 0x672e, 0x9edc, 0x5145, 0x5fe0, 0x6c96,
|
||||
0x87f2, 0x885d, 0x8877, 0x5074, 0x4ec4, 0x53a0, 0x60fb, 0x6e2c,
|
||||
0x5c64, 0x5247, 0x52c5, 0x98ed, 0x89aa, 0x4e03, 0x67d2, 0x6f06,
|
||||
0x4fb5, 0x5be2, 0x6795, 0x6c88, 0x6d78, 0x741b, 0x7827, 0x91dd,
|
||||
0x937c, 0x87c4, 0x79e4, 0x7a31, 0x502c, 0x5353, 0x5544, 0x577c,
|
||||
0xfa01, 0x6258, 0xfa02, 0x64e2, 0x666b, 0x67dd, 0x6fc1, 0x6fef,
|
||||
0x7422, 0x7438, 0x8a17, 0x9438, 0x5451, 0x5606, 0x5766, 0x5f48,
|
||||
0x619a, 0x6b4e, 0x7058, 0x70ad, 0x7dbb, 0x8a95, 0x596a, 0x812b,
|
||||
0x63a2, 0x7708, 0x803d, 0x8caa, 0x5854, 0x642d, 0x69bb, 0x5b95,
|
||||
0x5e11, 0x6e6f, 0xfa03, 0x8569, 0xfa04, 0x64c7, 0x6fa4, 0x6491,
|
||||
0x615f, 0x6876, 0xfa05, 0x75db, 0x7b52, 0x7d71, 0x901a, 0x615d,
|
||||
0x7279, 0x95d6, 0x5224, 0x5742, 0x677f, 0x7248, 0x74e3, 0x8ca9,
|
||||
0x8fa6, 0x9211, 0x962a, 0x516b, 0x53ed, 0x634c, 0x5f6d, 0x6f8e,
|
||||
0x70f9, 0x81a8, 0x610e, 0x4fbf, 0x504f, 0x6241, 0x7247, 0x7bc7,
|
||||
0x7de8, 0x7fe9, 0x904d, 0x97ad, 0x9a19, 0x8cb6, 0x576a, 0x5e73,
|
||||
0x67b0, 0x840d, 0x8a55, 0x5e45, 0x66b4, 0x66dd, 0x7011, 0x7206,
|
||||
0xfa07, 0x54c1, 0x7a1f, 0x6953, 0x8af7, 0x8c4a, 0x98a8, 0x99ae,
|
||||
0x5339, 0x5f3c, 0x5fc5, 0x6ccc, 0x73cc, 0x7562, 0x758b, 0x7b46,
|
||||
0x82fe, 0x999d, 0x4e4f, 0x903c, 0x58d1, 0x5b78, 0x8650, 0x8b14,
|
||||
0x9db4, 0x5bd2, 0x6068, 0x608d, 0x65f1, 0x6c57, 0x6f22, 0x6fa3,
|
||||
0x701a, 0x7f55, 0x7ff0, 0x9591, 0x9592, 0x9650, 0x97d3, 0x5272,
|
||||
0x8f44, 0x51fd, 0x542b, 0x54b8, 0x5563, 0x558a, 0x6abb, 0x6db5,
|
||||
0x7dd8, 0x8266, 0x929c, 0x9677, 0x9e79, 0x5408, 0x54c8, 0x76d2,
|
||||
0x86e4, 0x95a4, 0x95d4, 0x965c, 0x4ea2, 0x4f09, 0x59ee, 0x5ae6,
|
||||
0x5df7, 0x6052, 0x6297, 0x676d, 0x6841, 0x6c86, 0x6e2f, 0x7f38,
|
||||
0x809b, 0x822a, 0xfa08, 0xfa09, 0x9805, 0x52be, 0x6838, 0x5016,
|
||||
0x5e78, 0x674f, 0x8347, 0x884c, 0x4eab, 0x5411, 0x56ae, 0x73e6,
|
||||
0x9115, 0x97ff, 0x9909, 0x9957, 0x9999, 0x61b2, 0x6af6, 0x737b,
|
||||
0x8ed2, 0x6b47, 0x96aa, 0x9a57, 0x5955, 0x7200, 0x8d6b, 0x9769,
|
||||
0x4fd4, 0x5cf4, 0x5f26, 0x61f8, 0x665b, 0x6ceb, 0x70ab, 0x7384,
|
||||
0x73b9, 0x73fe, 0x7729, 0x774d, 0x7d43, 0x7d62, 0x7e23, 0x8237,
|
||||
0x8852, 0xfa0a, 0x8ce2, 0x9249, 0x986f, 0x5b51, 0x7a74, 0x8840,
|
||||
0x9801, 0x5acc, 0x4fe0, 0x5354, 0x593e, 0x5cfd, 0x633e, 0x6d79,
|
||||
0x72f9, 0x8105, 0x8107, 0x83a2, 0x92cf, 0x9830, 0x4ea8, 0x5144,
|
||||
0x5211, 0x578b, 0x5f62, 0x6cc2, 0x6ece, 0x7005, 0x7050, 0x70af,
|
||||
0x7192, 0x73e9, 0x7469, 0x834a, 0x87a2, 0x8861, 0x9008, 0x90a2,
|
||||
0x93a3, 0x99a8, 0x60d1, 0x6216, 0x9177, 0x5a5a, 0x660f, 0x6df7,
|
||||
0x6e3e, 0x743f, 0x9b42, 0x5ffd, 0x60da, 0x7b0f, 0x54c4, 0x5f18,
|
||||
0x6c5e, 0x6cd3, 0x6d2a, 0x70d8, 0x7d05, 0x8679, 0x8a0c, 0x9d3b,
|
||||
0xfa0b, 0x64f4, 0x652b, 0x78ba, 0x78bb, 0x7a6b, 0x4e38, 0x559a,
|
||||
0x5950, 0x5ba6, 0x5e7b, 0x60a3, 0x63db, 0x6b61, 0x6665, 0x6853,
|
||||
0x6e19, 0x7165, 0x74b0, 0x7d08, 0x9084, 0x9a69, 0x9c25, 0x6d3b,
|
||||
0x6ed1, 0x733e, 0x8c41, 0x95ca, 0x51f0, 0x5e4c, 0x5fa8, 0x604d,
|
||||
0x60f6, 0x6130, 0x614c, 0x6643, 0x6644, 0x69a5, 0x6cc1, 0x6e5f,
|
||||
0x6ec9, 0x6f62, 0x714c, 0x749c, 0x7687, 0x7bc1, 0x7c27, 0x8352,
|
||||
0x8757, 0x9051, 0x968d, 0x9ec3, 0x5283, 0x7372, 0x5b96, 0x6a6b,
|
||||
0x9404, 0x52db, 0x52f3, 0x5864, 0x58ce, 0x7104, 0x718f, 0x71fb,
|
||||
0x85b0, 0x8a13, 0x6688, 0x85a8, 0x55a7, 0x6684, 0x714a, 0x8431,
|
||||
0x6064, 0x8b4e, 0x9df8, 0x5147, 0x51f6, 0x5308, 0x6d36, 0x80f8,
|
||||
0x9ed1, 0x6615, 0x6b23, 0x7098, 0x75d5, 0x5403, 0x5c79, 0x7d07,
|
||||
0x8a16, 0x6b20, 0x6b3d, 0x6b46, 0x5438, 0x6070, 0x6d3d, 0x7fd5,
|
||||
0x8208, 0x8a70, 0xfa0b
|
||||
];
|
||||
|
||||
const RO_HANJA = [
|
||||
0x4e6b, 0x559d, 0x66f7, 0x6e34, 0x78a3, 0x7aed, 0x845b, 0x8910,
|
||||
0x874e, 0x97a8, 0x4e5e, 0x5091, 0x6770, 0x6840, 0x6289, 0x6c7a,
|
||||
0x6f54, 0x7d50, 0x7f3a, 0x8a23, 0x6c68, 0xf904, 0x9aa8, 0x522e,
|
||||
0x605d, 0x62ec, 0x9002, 0x5800, 0x5c48, 0x6398, 0x7a9f, 0x53a5,
|
||||
0x7357, 0x8568, 0x8e76, 0x95d5, 0x6a58, 0xf909, 0x4f76, 0x5409,
|
||||
0x62ee, 0x6854, 0x634f, 0x637a, 0x8a25, 0x64bb, 0x6fbe, 0x737a,
|
||||
0x75b8, 0x9054, 0x4e6d, 0x7a81, 0x524c, 0x8fa3, 0x51bd, 0x5217,
|
||||
0x52a3, 0x6d0c, 0x70c8, 0x88c2, 0x5f8b, 0x6144, 0x6817, 0xf961,
|
||||
0x551c, 0x62b9, 0x672b, 0x6cab, 0x8309, 0x896a, 0x977a, 0x6ec5,
|
||||
0x8511, 0x6b7f, 0x6c92, 0x52ff, 0x6c95, 0x7269, 0x5bc6, 0x871c,
|
||||
0x8b10, 0x52c3, 0x62d4, 0x64a5, 0x6e24, 0x6f51, 0x767c, 0x8dcb,
|
||||
0x91b1, 0x9262, 0x9aee, 0x9b43, 0x4f10, 0x7b4f, 0x7f70, 0x95a5,
|
||||
0x5225, 0x77a5, 0x9c49, 0x9f08, 0x4e76, 0xf967, 0x4f5b, 0x5f17,
|
||||
0x5f7f, 0x62c2, 0x4e77, 0x6492, 0x6bba, 0x715e, 0x85a9, 0x5368,
|
||||
0x5c51, 0x6954, 0x6cc4, 0x6d29, 0x6e2b, 0x820c, 0x859b, 0x893b,
|
||||
0x8a2d, 0x8aaa, 0x96ea, 0x9f67, 0x7387, 0x620c, 0x8853, 0x8ff0,
|
||||
0x9265, 0x745f, 0x819d, 0x8768, 0x5931, 0x5ba4, 0x5be6, 0x6089,
|
||||
0x65a1, 0x8b01, 0x8ecb, 0x95bc, 0x5b7c, 0x8616, 0xf99c, 0xf99d,
|
||||
0xf99e, 0x6085, 0x6d85, 0xf99f, 0x71b1, 0xf9a0, 0xf9a1, 0x95b1,
|
||||
0x5140, 0x66f0, 0x851a, 0x9b31, 0x4e90, 0x6708, 0x8d8a, 0x925e,
|
||||
0xf9d8, 0xf9d9, 0xf9da, 0xf9db, 0x807f, 0x4e59, 0x4e00, 0x4f5a,
|
||||
0x4f7e, 0x58f9, 0x65e5, 0x6ea2, 0x9038, 0x93b0, 0x99b9, 0x5207,
|
||||
0x622a, 0x6298, 0x6d59, 0x7664, 0x7aca, 0x7bc0, 0x7d76, 0x5352,
|
||||
0x62d9, 0x731d, 0x8301, 0x6adb, 0x4f84, 0x53f1, 0x59ea, 0x5ac9,
|
||||
0x5e19, 0x684e, 0x74c6, 0x75be, 0x79e9, 0x7a92, 0x81a3, 0x86ed,
|
||||
0x8cea, 0x8dcc, 0x8fed, 0x5239, 0x5bdf, 0x64e6, 0x672d, 0x7d2e,
|
||||
0x51f8, 0x54f2, 0x5586, 0x5fb9, 0x64a4, 0x6f88, 0x7db4, 0x8f1f,
|
||||
0x8f4d, 0x9435, 0x64ae, 0x51fa, 0x672e, 0x9edc, 0x4e03, 0x67d2,
|
||||
0x6f06, 0x596a, 0x812b, 0x516b, 0x53ed, 0x634c, 0x5339, 0x5f3c,
|
||||
0x5fc5, 0x6ccc, 0x73cc, 0x7562, 0x758b, 0x7b46, 0x82fe, 0x999d,
|
||||
0x5272, 0x8f44, 0x6b47, 0x5b51, 0x7a74, 0x8840, 0x9801, 0x5ffd,
|
||||
0x60da, 0x7b0f, 0x6d3b, 0x6ed1, 0x733e, 0x8c41, 0x95ca, 0x6064,
|
||||
0x8b4e, 0x9df8, 0x5403, 0x5c79, 0x7d07, 0x8a16, 0x8a70,
|
||||
];
|
||||
|
||||
const regNormalFixed = new RegExp(`/(?:${PRE_REG_NORMAL_FIXED.join('|')})$/iu`);
|
||||
const regSpecialChar = new RegExp(`/(?:${PRE_REG_SPECIAL_CHAR.join('|')})$/iu`);
|
||||
const regSpecialRo = new RegExp(`/(?:${PRE_REG_SPECIAL_RO.join('|')})$/iu`);
|
||||
|
||||
const jongsungHanja = new Set<number>();
|
||||
for (const hanjaCode of JONGSUNG_HANJA) {
|
||||
jongsungHanja.add(hanjaCode);
|
||||
}
|
||||
const roHanja = new Set<number>();
|
||||
for (const hanjaCode of RO_HANJA) {
|
||||
roHanja.add(hanjaCode);
|
||||
}
|
||||
const mapPostPosition = new Map<string, string>();
|
||||
for (const [key, val] of Object.entries(DEFAULT_POSTPOSITION)) {
|
||||
mapPostPosition.set(`(${key})${val}`, key);
|
||||
mapPostPosition.set(key, key);
|
||||
mapPostPosition.set(val, key);
|
||||
}
|
||||
|
||||
function checkText(text: string, isRo: boolean): boolean {
|
||||
if (regNormalFixed.test(text)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (regSpecialChar.test(text)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isRo && regSpecialRo.test(text)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkCode(code: number, isRo: boolean): boolean {
|
||||
const jongsung = (code - KO_START_CODE) % 28;
|
||||
if (jongsung === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isRo && jongsung === 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function check(text: string, type: string): boolean {
|
||||
|
||||
const htarget = text.replace(REG_INVALID_CHAR_W_HANJA, ' ').replace(REG_TARGET_CHAR, '$1');
|
||||
if (!htarget) {
|
||||
return false;
|
||||
}
|
||||
const hcode = htarget.charAt(htarget.length - 1).charCodeAt(0);
|
||||
const isRo = type === '로' || type === '으로';
|
||||
|
||||
if (HANJA_START_CODE <= hcode && hcode <= HANJA_FINISH_CODE) {
|
||||
if (isRo && roHanja.has(hcode)) {
|
||||
return false;
|
||||
}
|
||||
if (jongsungHanja.has(hcode)) {
|
||||
return true;
|
||||
}
|
||||
if (hcode < KO_START_CODE || KO_FINISH_CODE < hcode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const target = text.replace(REG_INVALID_CHAR, ' ').replace(REG_TARGET_CHAR, '$1');
|
||||
const code = target.charAt(target.length - 1).charCodeAt(0);
|
||||
|
||||
const isKorean = KO_START_CODE <= code && code <= KO_FINISH_CODE;
|
||||
|
||||
return isKorean ? checkCode(code, isRo) : checkText(target, isRo);
|
||||
}
|
||||
|
||||
export function pick(text: string|number, wJongsung: string, woJongsung = ''): string {
|
||||
/* NOTE:원본 코드와 인자 순서가 다름.
|
||||
* 원본은 pick('바람', '랑', '이랑'); 이었다면 pick('바람', '이랑', '랑'); 으로 바뀜.
|
||||
* pick('바람', '은', '는'); JosaUtil.pick('바람', '이', '가');처럼 쓰기 위해서임.
|
||||
*/
|
||||
if (!text) {
|
||||
text = '';
|
||||
} else if(typeof text === 'number'){
|
||||
text = String(text);
|
||||
}
|
||||
|
||||
if(!woJongsung){
|
||||
if(!mapPostPosition.has(wJongsung)){
|
||||
throw `올바르지 않은 조사 지정: ${wJongsung}`;
|
||||
}
|
||||
wJongsung = unwrap_err(mapPostPosition.get(wJongsung), Error, `올바르지 않은 조사 지정: ${wJongsung}`);
|
||||
woJongsung = DEFAULT_POSTPOSITION[wJongsung as keyof typeof DEFAULT_POSTPOSITION];
|
||||
}
|
||||
|
||||
return check(text, wJongsung) ? wJongsung : woJongsung;
|
||||
}
|
||||
|
||||
export function put(text: string, wJongsung: string, woJongsung = ''): string{
|
||||
return `${text}${pick(text, wJongsung, woJongsung)}`;
|
||||
}
|
||||
|
||||
export function fix(wJongsung: string, woJongsung = ''){
|
||||
if(!woJongsung){
|
||||
if(!mapPostPosition.has(wJongsung)){
|
||||
throw `올바르지 않은 조사 지정: ${wJongsung}`;
|
||||
}
|
||||
wJongsung = unwrap_err(mapPostPosition.get(wJongsung), Error, `올바르지 않은 조사 지정: ${wJongsung}`);
|
||||
woJongsung = DEFAULT_POSTPOSITION[wJongsung as keyof typeof DEFAULT_POSTPOSITION];
|
||||
}
|
||||
return function(text: string){
|
||||
return put(text, wJongsung, woJongsung);
|
||||
}
|
||||
}
|
||||
|
||||
export function batch(text: string, decorator = ';'){
|
||||
const regExp = new RegExp(`${decorator}([^${decorator}]+)${decorator}([^${decorator}]*)${decorator}([^${decorator}]+)${decorator}`, 'g');
|
||||
|
||||
let matchRes;
|
||||
let lastIndex = 0;
|
||||
|
||||
const result: string[] = [];
|
||||
|
||||
while ((matchRes = regExp.exec(text)) !== null) {
|
||||
const {
|
||||
0: partAll,
|
||||
1: body,
|
||||
2: filler,
|
||||
3: wJongsung,
|
||||
index,
|
||||
} = matchRes;
|
||||
if(lastIndex != index){
|
||||
result.push(text.slice(lastIndex, index));
|
||||
}
|
||||
|
||||
result.push(body, filler, pick(body, wJongsung));
|
||||
|
||||
lastIndex = index + partAll.length;
|
||||
}
|
||||
if(lastIndex != text.length){
|
||||
result.push(text.slice(lastIndex));
|
||||
}
|
||||
|
||||
return result.join('');
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
export class NotNullExpected extends TypeError {
|
||||
public override name = 'NotNullExpected';
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
export interface RNG {
|
||||
|
||||
/**
|
||||
* nextInt()가 반환 가능한 최댓값
|
||||
*/
|
||||
getMaxInt(): number;
|
||||
|
||||
nextBytes(bytes: number): Promise<Uint8Array>;
|
||||
nextBits(bits: number): Promise<Uint8Array>;
|
||||
|
||||
nextInt(max?: number): Promise<number>;
|
||||
nextFloat1(): Promise<number>;
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
import type { RNG } from './RNG.js';
|
||||
|
||||
export class RandUtil {
|
||||
constructor(protected rng: RNG) {
|
||||
|
||||
}
|
||||
|
||||
public nextFloat1(): Promise<number> {
|
||||
return this.rng.nextFloat1();
|
||||
}
|
||||
|
||||
public async nextRange(min: number, max: number): Promise<number> {
|
||||
const range = max - min;
|
||||
return await this.nextFloat1() * (range) + min;
|
||||
}
|
||||
|
||||
public async nextRangeInt(min: number, max: number): Promise<number> {
|
||||
const range = max - min;
|
||||
return await this.rng.nextInt(range) + min;
|
||||
}
|
||||
|
||||
public nextInt(max?: number): Promise<number> {
|
||||
return this.rng.nextInt(max);
|
||||
}
|
||||
|
||||
public async nextBit(): Promise<boolean> {
|
||||
const view = new DataView(await this.rng.nextBits(1) as ArrayBufferLike);
|
||||
return view.getUint8(0) != 0;
|
||||
}
|
||||
|
||||
public async nextBool(prob = 0.5): Promise<boolean> {
|
||||
if (prob >= 1) {
|
||||
return true;
|
||||
}
|
||||
if (prob === 0.5){
|
||||
return this.nextBit();
|
||||
}
|
||||
if (prob <= 0){
|
||||
return false;
|
||||
}
|
||||
return await this.nextFloat1() < prob;
|
||||
}
|
||||
|
||||
public async shuffle<T>(srcArray: T[]): Promise<T[]> {
|
||||
const cnt = srcArray.length;
|
||||
if(cnt === 0){
|
||||
return [];
|
||||
}
|
||||
if (cnt > this.rng.getMaxInt()) {
|
||||
throw 'Invalid random int range';
|
||||
}
|
||||
|
||||
const result: T[] = Array.from(srcArray);
|
||||
for (let srcIdx = 0; srcIdx < cnt; srcIdx += 1) {
|
||||
const destIdx = await this.rng.nextInt(cnt - srcIdx - 1) + srcIdx;
|
||||
if(srcIdx === destIdx){
|
||||
continue;
|
||||
}
|
||||
[result[srcIdx], result[destIdx]] = [result[destIdx], result[srcIdx]];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//Object는 integer key에 예외가 있어 shuffleAssoc은 없음
|
||||
|
||||
public async choice<T>(items: T[] | Record<string | number, T> | Set<T>): Promise<T> {
|
||||
if (items instanceof Array) {
|
||||
if(items.length === 0){
|
||||
throw new Error('Empty items');
|
||||
}
|
||||
const idx = await this.rng.nextInt(items.length - 1);
|
||||
return items[idx];
|
||||
}
|
||||
|
||||
if (items instanceof Set) {
|
||||
return this.choice(Array.from(items.values()));
|
||||
}
|
||||
|
||||
return items[await this.choice(Array.from(Object.keys(items)))];
|
||||
}
|
||||
|
||||
public async choiceUsingWeight(items: Record<string | number, number>): Promise<string | number> {
|
||||
if(Object.keys(items).length === 0){
|
||||
throw new Error('Empty items');
|
||||
}
|
||||
let sum = 0;
|
||||
for (const value of Object.values(items)) {
|
||||
if (value <= 0) {
|
||||
continue;
|
||||
}
|
||||
sum += value;
|
||||
}
|
||||
|
||||
let rd = await this.nextFloat1() * sum;
|
||||
|
||||
for (const [item, value] of Object.entries(items)) {
|
||||
if (value <= 0) {
|
||||
if (rd <= 0) {
|
||||
return item;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rd <= value) {
|
||||
return item;
|
||||
}
|
||||
rd -= value;
|
||||
}
|
||||
|
||||
throw new Error('Unreacheable');
|
||||
}
|
||||
|
||||
public async choiceUsingWeightPair<T>(items: [T, number][]): Promise<T> {
|
||||
if(items.length === 0){
|
||||
throw new Error('Empty items');
|
||||
}
|
||||
let sum = 0;
|
||||
for (const [, value] of items) {
|
||||
if (value <= 0) {
|
||||
continue;
|
||||
}
|
||||
sum += value;
|
||||
}
|
||||
|
||||
let rd = await this.nextFloat1() * sum;
|
||||
|
||||
for (const [item, value] of items) {
|
||||
if (value <= 0) {
|
||||
if (rd <= 0) {
|
||||
return item;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rd <= value) {
|
||||
return item;
|
||||
}
|
||||
rd -= value;
|
||||
}
|
||||
|
||||
throw new Error('Unreacheable');
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
export class RuntimeError extends Error {
|
||||
public override name = 'RuntimeError';
|
||||
constructor(public override message: string = '') {
|
||||
super(message);
|
||||
}
|
||||
override toString(): string {
|
||||
if (this.message) {
|
||||
return this.name + ': ' + this.message;
|
||||
}
|
||||
else {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
export interface StateIncrementer {
|
||||
(state: number): Promise<number>;
|
||||
}
|
||||
|
||||
export type NumberGroup = {
|
||||
start: number;
|
||||
remain: number;
|
||||
}
|
||||
|
||||
const AllocatorGroupBucketSize = 100;
|
||||
const AllocatorPreserveThreshold = 50;
|
||||
|
||||
export function* numberGenerator(numberGroups: NumberGroup[]): Generator<number, null> {
|
||||
for (const numberGroup of numberGroups) {
|
||||
for (let i = 0; i < numberGroup.remain; i++) {
|
||||
yield numberGroup.start + i;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export class UniqueNumberAllocator {
|
||||
private preservedNumbers: NumberGroup[];
|
||||
private incrementer: StateIncrementer;
|
||||
private totalRemain: number;
|
||||
private promisedCnt: number;
|
||||
private promise: Promise<void>;
|
||||
|
||||
public constructor(incrementer: StateIncrementer, initialState?: NumberGroup) {
|
||||
this.incrementer = incrementer;
|
||||
if (!initialState) {
|
||||
this.preservedNumbers = [];
|
||||
this.totalRemain = 0;
|
||||
}
|
||||
else {
|
||||
if (initialState.remain < 1) {
|
||||
throw new Error('initialState.remain must be greater than 0');
|
||||
}
|
||||
this.preservedNumbers = [initialState];
|
||||
this.totalRemain = initialState.remain;
|
||||
}
|
||||
this.promisedCnt = 0;
|
||||
this.promise = Promise.resolve();
|
||||
this.preserveNext();
|
||||
}
|
||||
|
||||
public static async generate(incrementer: StateIncrementer): Promise<UniqueNumberAllocator> {
|
||||
const initialStateEnd = await incrementer(AllocatorGroupBucketSize);
|
||||
const initialState: NumberGroup = {
|
||||
start: initialStateEnd - AllocatorGroupBucketSize + 1,
|
||||
remain: AllocatorGroupBucketSize,
|
||||
}
|
||||
return new UniqueNumberAllocator(incrementer, initialState);
|
||||
}
|
||||
|
||||
private preserveNext(): void {
|
||||
if (this.promisedCnt + this.totalRemain >= AllocatorGroupBucketSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.totalRemain >= AllocatorPreserveThreshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
const waiter = this.promise;
|
||||
|
||||
this.promise = (async () => {
|
||||
this.promisedCnt += AllocatorGroupBucketSize;
|
||||
const nextP = this.incrementer(AllocatorGroupBucketSize);
|
||||
await waiter;
|
||||
const next = await nextP;
|
||||
if (this.preservedNumbers.length > 0) {
|
||||
const last = this.preservedNumbers[this.preservedNumbers.length - 1];
|
||||
if (last.start + last.remain === next - AllocatorGroupBucketSize + 1) {
|
||||
// 마지막 그룹과 연속됨
|
||||
last.remain += AllocatorGroupBucketSize;
|
||||
this.totalRemain += AllocatorGroupBucketSize;
|
||||
this.promisedCnt -= AllocatorGroupBucketSize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
const nextGroup: NumberGroup = {
|
||||
start: next - AllocatorGroupBucketSize + 1,
|
||||
remain: AllocatorGroupBucketSize,
|
||||
}
|
||||
this.preservedNumbers.push(nextGroup);
|
||||
this.totalRemain += AllocatorGroupBucketSize;
|
||||
this.promisedCnt -= AllocatorGroupBucketSize;
|
||||
})();
|
||||
}
|
||||
|
||||
public async allocateOne(): Promise<number> {
|
||||
if (this.totalRemain > 0) {
|
||||
const head = this.preservedNumbers[0];
|
||||
if (head.remain > 1) {
|
||||
const next = head.start;
|
||||
head.start++;
|
||||
head.remain--;
|
||||
this.totalRemain--;
|
||||
this.preserveNext();
|
||||
return next;
|
||||
}
|
||||
else {
|
||||
this.preservedNumbers.shift();
|
||||
this.totalRemain--;
|
||||
this.preserveNext();
|
||||
return head.start;
|
||||
}
|
||||
}
|
||||
|
||||
const next = (await this.allocate(1)).next().value;
|
||||
if (next === null) {
|
||||
throw new Error('incrementer failed to allocate enough numbers');
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
public async allocate(n: number): Promise<Generator<number, null>> {
|
||||
n = Math.ceil(n);
|
||||
if (n < 1) {
|
||||
throw new Error('n must be greater than 0');
|
||||
}
|
||||
|
||||
if (n > this.totalRemain + this.promisedCnt) {
|
||||
const endP = this.incrementer(n);
|
||||
this.preserveNext();
|
||||
const end = await endP;
|
||||
|
||||
return numberGenerator([{
|
||||
start: end - n + 1,
|
||||
remain: n,
|
||||
}]);
|
||||
}
|
||||
|
||||
const result: NumberGroup[] = [];
|
||||
|
||||
if (this.totalRemain > 0) {
|
||||
const head = this.preservedNumbers[0];
|
||||
const headRemain = head.remain;
|
||||
|
||||
if (n < headRemain) {
|
||||
result.push({
|
||||
start: head.start,
|
||||
remain: n,
|
||||
});
|
||||
head.start += n;
|
||||
head.remain -= n;
|
||||
this.totalRemain -= n;
|
||||
this.preserveNext();
|
||||
return numberGenerator(result);
|
||||
}
|
||||
if (n === headRemain) {
|
||||
this.preservedNumbers.shift();
|
||||
result.push(head);
|
||||
this.totalRemain -= n;
|
||||
this.preserveNext();
|
||||
return numberGenerator(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//assert n <= this.totalRemain + this.promisedRemain
|
||||
|
||||
if (n > this.totalRemain) {
|
||||
await this.promise;
|
||||
if (n > this.totalRemain) {
|
||||
throw new Error('incrementer failed to allocate enough numbers');
|
||||
}
|
||||
}
|
||||
|
||||
this.totalRemain -= n;
|
||||
this.preserveNext();
|
||||
|
||||
let remain = n;
|
||||
let idx = 0;
|
||||
while (remain > 0) {
|
||||
const head = this.preservedNumbers[idx];
|
||||
if (head.remain <= remain) {
|
||||
remain -= head.remain;
|
||||
result.push(head);
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push({
|
||||
start: head.start,
|
||||
remain: remain,
|
||||
});
|
||||
head.start += remain;
|
||||
head.remain -= remain;
|
||||
remain = 0;
|
||||
break;
|
||||
}
|
||||
this.preservedNumbers = this.preservedNumbers.slice(idx);
|
||||
|
||||
return numberGenerator(result);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { webcrypto } from "crypto";
|
||||
|
||||
const subtle = webcrypto.subtle;
|
||||
type BufferSource = ArrayBufferView | ArrayBuffer;
|
||||
|
||||
export async function AES_GCM_Encrypt(key: BufferSource, iv: BufferSource, msg: BufferSource, aad?: BufferSource): Promise<ArrayBuffer> {
|
||||
const keyObj = await subtle.importKey("raw", key, {
|
||||
name: "AES-GCM",
|
||||
}, false, ["encrypt"]);
|
||||
|
||||
const ciphertext = await subtle.encrypt({
|
||||
name: "AES-GCM",
|
||||
iv,
|
||||
additionalData: aad
|
||||
}, keyObj, msg);
|
||||
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
|
||||
export async function AES_GCM_Decrypt(key: BufferSource, iv: BufferSource, ciphertext: BufferSource, aad?: BufferSource): Promise<ArrayBuffer> {
|
||||
const keyObj = await subtle.importKey("raw", key, {
|
||||
name: "AES-GCM",
|
||||
}, false, ["decrypt"]);
|
||||
|
||||
const plaintext = await subtle.decrypt({
|
||||
name: "AES-GCM",
|
||||
iv: iv,
|
||||
additionalData: aad
|
||||
}, keyObj, ciphertext);
|
||||
//아마도 tag 검증 실패시 예외가 발생할 것으로 예상
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
type Entries<T> = {
|
||||
[K in keyof T]: [K, T[K]];
|
||||
}[keyof T][];
|
||||
|
||||
export function entriesWithType<T extends object>(value: T): Entries<T>{
|
||||
return Object.entries(value) as unknown as Entries<T>;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
import { formatTime } from './formatTime.js';
|
||||
export function getDateTimeNow(withFraction = false): string {
|
||||
return formatTime(new Date(), withFraction);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export function hexToRgb(hex: string): { r: number; g: number; b: number; } | null {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16)
|
||||
} : null;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { unwrap } from ".//unwrap.js";
|
||||
import { hexToRgb } from "./hexToRgb.js";
|
||||
|
||||
export function isBrightColor(color: string): boolean {
|
||||
const cv = unwrap(hexToRgb(color));
|
||||
if ((cv.r * 0.299 + cv.g * 0.587 + cv.b * 0.114) > 140) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export function isNotNull<T>(value: T|null|undefined):value is T{
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export function joinYearMonth(year: number, month: number): number {
|
||||
return year * 12 + month - 1;
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
import { every, isString } from "lodash-es";
|
||||
|
||||
type JsonifiableLite =
|
||||
string | number | boolean | bigint | null | undefined |
|
||||
Date | ArrayBuffer | SharedArrayBuffer | ArrayBufferView |
|
||||
JsonifiableLite[] | { [key: string]: JsonifiableLite };
|
||||
|
||||
export type Jsonifiable =
|
||||
JsonifiableLite |
|
||||
Jsonifiable[] |
|
||||
Map<JsonifiableLite, Jsonifiable> |
|
||||
Set<Jsonifiable> |
|
||||
{ jsonify(): Jsonifiable } |
|
||||
{ [key: string]: Jsonifiable };
|
||||
|
||||
export type Jsonified<T extends Jsonifiable> =
|
||||
T extends string ? string :
|
||||
T extends number ? number :
|
||||
T extends boolean ? boolean :
|
||||
T extends bigint ? string :
|
||||
T extends null ? null :
|
||||
T extends undefined ? undefined :
|
||||
T extends Date ? string :
|
||||
T extends ArrayBuffer ? string :
|
||||
T extends SharedArrayBuffer ? string :
|
||||
T extends ArrayBufferView ? string :
|
||||
T extends (infer K extends Jsonifiable)[] ? Jsonified<K>[] :
|
||||
T extends Map<infer K extends Jsonifiable, infer V extends Jsonifiable> ? (
|
||||
K extends string ? { [key in string]: Jsonified<V> } : [Jsonified<K>, Jsonified<V>][]) :
|
||||
T extends Set<infer V extends Jsonifiable> ? Jsonified<V>[] :
|
||||
T extends object ? (
|
||||
T extends { jsonify(): infer V extends Jsonifiable } ? Jsonified<V> : //HACK: jsonify()는 Jsonified여야 함
|
||||
{[key in keyof T]: Jsonified<T[key]>}):
|
||||
T extends unknown ? unknown :
|
||||
never;
|
||||
|
||||
|
||||
/**
|
||||
* Convert any object to JSON-safe object
|
||||
*/
|
||||
export function jsonify<T extends Jsonifiable>(item: T): Jsonified<T> {
|
||||
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return item as any;
|
||||
}
|
||||
|
||||
if (typeof item === 'bigint') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return item.toString() as any;
|
||||
}
|
||||
|
||||
if (item === undefined || item === null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return item as any;
|
||||
}
|
||||
|
||||
if (item instanceof Date) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return item.toISOString() as any;
|
||||
}
|
||||
|
||||
if (item instanceof ArrayBuffer || item instanceof SharedArrayBuffer) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return Buffer.from(item).toString('base64') as any;
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(item)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return Buffer.from(item.buffer, item.byteOffset, item.byteLength).toString('base64') as any;
|
||||
}
|
||||
|
||||
if (Array.isArray(item)) {
|
||||
//HACK: depth hack
|
||||
const result: Jsonified<string>[] = [];
|
||||
for (const v of item) {
|
||||
result.push(jsonify(v as string) as Jsonified<string>);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (item instanceof Map) {
|
||||
//HACK: depth hack
|
||||
|
||||
const onlyStringKey = every(item.keys, isString);
|
||||
if (onlyStringKey) {
|
||||
const result: { [key: string]: Jsonified<string> } = {};
|
||||
for (const [k, v] of item.entries()) {
|
||||
result[k as string] = jsonify(v as string) as Jsonified<string>;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
const result: [Jsonified<string>, Jsonified<string>][] = [];
|
||||
for (const [k, v] of item.entries()) {
|
||||
result.push([jsonify(k as string), jsonify(v as string)] as [Jsonified<string>, Jsonified<string>]);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (item instanceof Set) {
|
||||
const result: Jsonified<string>[] = [];
|
||||
for (const v of item.values()) {
|
||||
result.push(jsonify(v as string) as Jsonified<string>);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (typeof item === 'object') {
|
||||
if (typeof (item as { jsonify(): unknown }).jsonify === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return (item as { jsonify(): unknown }).jsonify() as any;
|
||||
}
|
||||
|
||||
const result: { [key: string]: Jsonified<string> } = {};
|
||||
for (const [k, v] of Object.entries(item)) {
|
||||
if (typeof k !== 'string') {
|
||||
continue;
|
||||
}
|
||||
if (typeof v === 'function') {
|
||||
continue;
|
||||
}
|
||||
result[k] = jsonify(v as string) as Jsonified<string>;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
throw new Error(`jsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { mb_strwidth } from ".//mb_strwidth.js";
|
||||
|
||||
/**
|
||||
* mb_strimwidth
|
||||
* @param String
|
||||
* @param int
|
||||
* @param int
|
||||
* @param String
|
||||
* @return String
|
||||
* @see http://www.php.net/manual/function.mb-strimwidth.php
|
||||
*/
|
||||
export function mb_strimwidth(str: string, start: number, width: number, trimmarker = ''): string {
|
||||
const trimmakerWidth = mb_strwidth(trimmarker);
|
||||
const l = str.length;
|
||||
let trimmedLength = 0;
|
||||
const trimmedStr: string[] = [];
|
||||
for (let i = start; i < l; i++) {
|
||||
const c = str.charAt(i);
|
||||
const charWidth = mb_strwidth(c);
|
||||
const next = str.charAt(i + 1);
|
||||
const nextWidth = mb_strwidth(next);
|
||||
|
||||
trimmedLength += charWidth;
|
||||
trimmedStr.push(c);
|
||||
if (trimmedLength + trimmakerWidth + nextWidth > width) {
|
||||
trimmedStr.push(trimmarker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return trimmedStr.join('');
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
//https://gist.github.com/demouth/3217440
|
||||
/**
|
||||
* mb_strwidth
|
||||
* @see http://php.net/manual/function.mb-strwidth.php
|
||||
*/
|
||||
export function mb_strwidth(str: string): number {
|
||||
const l = str.length;
|
||||
let length = 0;
|
||||
for (let i = 0; i < l; i++) {
|
||||
const c = str.charCodeAt(i);
|
||||
if (0x0000 <= c && c <= 0x0019) {
|
||||
length += 0;
|
||||
} else if (0x0020 <= c && c <= 0x1FFF) {
|
||||
length += 1;
|
||||
} else if (0x2000 <= c && c <= 0xFF60) {
|
||||
length += 2;
|
||||
} else if (0xFF61 <= c && c <= 0xFF9F) {
|
||||
length += 1;
|
||||
} else if (0xFFA0 <= c) {
|
||||
length += 2;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
import type { ValuesOf } from "./defs.js";
|
||||
import { zip } from "lodash-es";
|
||||
|
||||
export function merge2DArrToObjectArr<T extends Record<string, unknown>>(column: (keyof T)[], list: ValuesOf<T>[][]): T[]{
|
||||
const result: T[] = [];
|
||||
for(const rawItem of list){
|
||||
const item: Record<string, unknown> = {};
|
||||
|
||||
if(column.length != rawItem.length){
|
||||
throw `column과 item의 길이가 같지 않습니다: ${column.length} != ${list.length}, ${JSON.stringify(item)}`;
|
||||
}
|
||||
|
||||
for(const [key, value] of zip(column, rawItem)){
|
||||
item[key as string] = value;
|
||||
}
|
||||
result.push(item as T);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { isString } from "lodash-es";
|
||||
|
||||
interface NameValuePair {
|
||||
name: string,
|
||||
value: string
|
||||
}
|
||||
|
||||
export function mergeKVArray(array : NameValuePair[]):Record<string, string|string[]>{
|
||||
const result:Record<string, string|string[]> = {};
|
||||
|
||||
for(const {name, value} of array){
|
||||
if(!isString(name)){
|
||||
throw new TypeError(`${name} is not string`);
|
||||
}
|
||||
if(!isString(value)){
|
||||
throw new TypeError(`${value} is not string`);
|
||||
}
|
||||
|
||||
if(name === '' || name === '[]'){
|
||||
continue;
|
||||
}
|
||||
if(name.length > 2 && name.slice(-2) == '[]'){
|
||||
const keyHead = name.slice(0, -2);
|
||||
if(!(keyHead in result)){
|
||||
result[keyHead] = [value];
|
||||
}
|
||||
else{
|
||||
(result[keyHead] as string[]).push(value);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
result[name] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
export function nl2br(text: string): string {
|
||||
return text.replace(/\n/g, "<br>");
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
|
||||
export function numberWithCommas(x: number): string {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
const charList = [
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z',
|
||||
];
|
||||
|
||||
export function randStr(len: number): string {
|
||||
const result = [];
|
||||
const charListLen = charList.length;
|
||||
let isStart = true;
|
||||
|
||||
while(len > 0){
|
||||
const randChrIdx = Math.floor(Math.random() * charListLen);
|
||||
if(isStart){
|
||||
if(randChrIdx == 0){
|
||||
continue;
|
||||
}
|
||||
isStart = false;
|
||||
}
|
||||
result.push(charList[randChrIdx]);
|
||||
len -= 1;
|
||||
}
|
||||
return result.join('');
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { webcrypto } from "node:crypto";
|
||||
|
||||
const subtle = webcrypto.subtle;
|
||||
|
||||
export async function sha256(msg: ArrayBuffer): Promise<ArrayBuffer>{
|
||||
return await subtle.digest('SHA-256', msg);
|
||||
}
|
||||
|
||||
export async function sha512(msg: ArrayBuffer): Promise<ArrayBuffer>{
|
||||
return await subtle.digest('SHA-512', msg);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { isInteger, isString } from "lodash-es";
|
||||
|
||||
export function simpleSerialize(...values : (string|number)[]): string{
|
||||
const result: string[] = [];
|
||||
for(const value of values){
|
||||
if(isString(value)){
|
||||
result.push(`str(${value.length},${value})`);
|
||||
continue;
|
||||
}
|
||||
if(isInteger(value)){
|
||||
result.push(`int(${value})`);
|
||||
continue;
|
||||
}
|
||||
const float6 = value.toLocaleString("en-US", {maximumFractionDigits: 6});
|
||||
result.push(`float(${float6})`);
|
||||
}
|
||||
return result.join('|');
|
||||
}
|
||||
Reference in New Issue
Block a user