| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827 |
- Reflect.defineProperty(String.prototype, 'decodeAtoB', {
- get(this: String){
- return decodeURIComponent(atob(this.valueOf()));
- },
- enumerable: true,
- configurable: false,
- });
- Reflect.defineProperty(String.prototype, 'encodeBtoA', {
- get(this: String){
- return btoa(encodeURIComponent(this.valueOf()));
- },
- enumerable: true,
- configurable: false,
- });
- Number.prototype.inRange = function(this: Number, a, b){
- let value = this.valueOf();
- if ([value, a, b].includes(NaN)) return false;
- let [va, vb] = [value - a, value - b].map(v => [-Infinity, Infinity].includes(v) ? v<0 ? -1 : 1 : v);
- return va * vb <= 0;
- }
- Reflect.defineProperty(Array.prototype, 'lastElement', {
- get(this: Array<any>){
- return this.length>0 ? Reflect.get(this, this.length-1) : undefined;
- },
- set(this: Array<any>, value: any){
- Reflect.set(this, this.length>0 ? this.length-1 : 0, value);
- },
- enumerable: true,
- configurable: false,
- });
- Array.prototype.forWait = async function(this: Array<any>, call){
- for(let i = 0; i < this.length; i++) await call(this[i], i, this);
- }
- // 检测全局命名空间是否存在
- const __Global__ = window ?? globalThis;
- if(!Reflect.has(__Global__, 'mtec')){
- Reflect.set(__Global__, 'mtec', {});
- Reflect.set(mtec, '__mtec__', 'Many technologies');
- }
- // 初始化子命名空间
- ['string', 'number', 'array', 'log', 'color', 'local', 'time']
- .forEach(space_name=>{
- if(!Reflect.has(mtec, space_name)){
- Reflect.set(mtec, space_name, {});
- Reflect.set(Reflect.get(mtec, space_name), '__space_description__', 'This is a mtec subnamespace for ' + space_name);
- }
- });
- mtec.vtype = function(value){
- let type = typeof value;
- return type=='object' ? value==null ? 'null' : Array.isArray(value) ? 'array' : 'object' : type;
- }
- mtec.same = function(a, b, record){
- if(a===b) return true;
- let [ta, tb] = [a, b].map(_=>mtec.vtype(_));
- if(ta!=tb) return [ta, tb].every(t=>['number', 'bigint'].includes(t)) ? a==b : false;
- if(!['array', 'object'].includes(ta)) return a==b;
- if(!record) record = {cache: [], mark: new Map(), list: []};
- let token = [a, b].map(v=>{
- if(record.mark.has(v)) return record.mark.get(v);
- let mark = mtec.string.randomToken(3, 36, _t=>!record.list.includes(_t));
- record.list.push(mark);
- record.mark.set(v, mark);
- return mark;
- }).sort().join('::');
- if(record.cache.includes(token)) return true;
- record.cache.push(token);
- let [key_a, key_b] = [a, b].map(v=>Reflect.ownKeys(v).filter(k=>v[k]!=undefined && v[k]!=null).sort());
- if(key_a.length==key_b.length && key_a.every((k, i)=>k==key_b[i])) return key_a.every(k=>mtec.same(a[k], b[k], record));
- return false;
- }
- mtec.pickValueByType = function<T extends [mtec.type_string, any][]>(values: any[], types: T){
- let map = values.reduce((m, v)=>{
- let t = mtec.vtype(v);
- if(m[t]==undefined) m[t] = [];
- Array.prototype.unshift.call(m[t], v);
- return m;
- }, {});
- return types.map(picker=>{
- let v = Reflect.get(map, picker[0]);
- return v ? v.length>1 ? Array.prototype.pop.call(v) : v[0] : picker[1];
- }) as mtec.TypeArray<mtec.PickFirst<T>>;
- }
- mtec.delay = function(delay, call, ...args){
- return new Promise((s, j)=>{
- let id = setTimeout((c, a)=>{
- clearTimeout(id);
- s(typeof c=='function' ? c(...a) : c);
- }, delay * 1000, call, args)
- });
- }
- mtec.drawLots = function(bucket){
- if(bucket.length<=0) return void 0;
- if(bucket.length==1) return bucket[0][0];
- let data_list = [];
- let weight_list = [];
- let total = 0;
- for(let [data, weight] of bucket){
- let v = Number(weight);
- if(!(v > 0)) continue;
- total += v;
- data_list.push(data);
- weight_list.push(total);
- }
- let point = Math.random() * total;
- let i = 0;
- while(point >= weight_list[i]) i++;
- return data_list[i];
- }
- mtec.fusionData = function(target, ...list){
- if(target instanceof Object){
- if(Array.isArray(target)){
- //@ts-ignore
- list.forEach(data=>Array.isArray(data) ? target.push(...data) : target.push(data));
- }else if(!(target instanceof Function)){
- let ls = list.filter(data=>data instanceof Object && !(data instanceof Function));
- let map = ls.reduce((m, data, i)=>{
- Reflect.ownKeys(data).forEach(key=>m.set(key, i));
- return m;
- }, new Map());
- //@ts-ignore
- map.forEach((i, key)=>Reflect.set(target, key, Reflect.get(ls[i], key)));
- }
- }else{
- if(typeof target == 'bigint'){
- list.forEach(data=>{
- switch(typeof data){
- //@ts-ignore
- case 'boolean': data = Number(data); case 'object': case 'undefined': data = BigInt(0); case 'number': if(isNaN(data)) data = 0; data = BigInt(data); break;
- //@ts-ignore
- case 'symbol': data = String(data); break;
- }
- // @ts-ignore
- target += data;
- })
- }else if(['string', 'symbol'].includes(typeof target)){
- //@ts-ignore
- target = String(target);
- //@ts-ignore
- list.forEach(data=>target += (typeof data=='symbol' ? String(data) : data));
- }else{
- list.forEach(data=>{
- switch(typeof data){
- //@ts-ignore
- case 'bigint': target = Number(target); if(isNaN(target)) target = BigInt(0); break;
- //@ts-ignore
- case 'symbol': data = String(data);
- }
- //@ts-ignore
- target += data;
- })
- }
- }
- return target as any;
- }
- mtec.cloneData = function(data, record){
- let t = mtec.vtype(data);
- if(['string', 'number', 'boolean', 'bigint', 'undefined', 'null'].includes(t)) return data;
- else if(t == 'function') return Function.prototype.bind.call(data, null);
- else if(t == 'symbol') return Symbol(data['description']);
- else{
- if(!record) record = new Map();
- if(record.has(data)) return record.get(data);
- let target;
- if(t=='array') target = [];
- else target = {};
- record.set(data, target);
- //@ts-ignore
- if(t=='array') data.forEach(el=>target.push(mtec.cloneData(el)));
- else{
- //@ts-ignore
- Reflect.ownKeys(data).forEach(key=>Reflect.set(target, key, Reflect.get(data, key)));
- //@ts-ignore
- Reflect.setPrototypeOf(target, Reflect.getPrototypeOf(data));
- }
- return target;
- }
- }
- mtec.CountAverage = class{
- private count = 0;
- private _average: number;
- constructor(init?: number){
- if(init) this.add(init);
- }
- public get average(){
- return this._average ?? 0;
- }
- public add(value: number){
- this.count++;
- this._average = this.average + (value - this.average) / this.count;
- return this._average;
- }
- public clean(){
- this.count = 0;
- this._average = 0;
- }
- }
- mtec.NudityPromise = class<V>{
- private inited: boolean;
- private status: 'waiting'|'resolve'|'reject';
- private result: any;
- private _resolve_call_: (value: V | PromiseLike<V>)=>void;
- private _reject_call_: (reason: any)=>void;
- public promise: Promise<V>;
- constructor(){
- this.inited = false;
- this.status = 'waiting';
- this.promise = new Promise((s, j)=>{
- this._resolve_call_ = s;
- this._reject_call_ = j;
- this.inited = true;
- this.reply();
- });
- }
- public resolve(value: V | PromiseLike<V>){
- this.re_call('resolve', value);
- }
- public reject(reason: any){
- this.re_call('reject', reason);
- }
- private re_call(status: 'resolve'|'reject', result: any){
- if(this.status=='waiting'){
- [this.status, this.result] = [status, result];
- this.reply();
- }
- }
- private reply(){
- if(this.inited && this.status!='waiting'){
- switch(this.status){
- case 'resolve': this._resolve_call_(this.result); break;
- case 'reject': this._reject_call_(this.result); break;
- }
- }
- }
- }
- mtec.JsonString = function(data){
- let tp = typeof data;
- if(tp != 'object') return JSON.stringify(data);
- if(data == null) return 'null';
- let copy_map: Map<any, any> = new Map();
- let token_map: Map<any, string> = new Map();
- let token_cache = [];
- let data_list = [data];
- copy_map.set(data, Array.isArray(data) ? [] : {});
- token_map.set(data, mtec.string.randomToken(5, 36, tlkn=>!token_cache.includes(tlkn)));
- for(let i = 0; i < data_list.length; i++){
- let item = data_list[i];
- let copy = copy_map.get(item);
- let key_list: Array<string|number|symbol> = Array.isArray(item) ? mtec.array.create(item.length, i=>i) : Reflect.ownKeys(item);
- let data_flag: Array<[string, string|number|symbol]> = [];
- for(let key of key_list){
- let value = Reflect.get(item, key);
- if(typeof value != 'object') Reflect.set(copy, key, value);
- else if(value == null) Reflect.set(copy, key, null);
- else if(token_map.has(value)) Reflect.set(copy, key, '<-[ref]->'+token_map.get(value));
- else{
- let token = mtec.string.randomToken(5, 36, t=>!token_cache.includes(t));
- let cp = Array.isArray(value) ? [] : {};
- token_map.set(value, token);
- copy_map.set(value, cp);
- data_list.push(value);
- if(Array.isArray(item)){
- Reflect.set(copy, key, cp);
- data_flag.push([token, key]);
- }else Reflect.set(copy, token+'<-[data]->'+String(key), cp);
- }
- }
- if(data_flag.length>0 && Array.isArray(item)) copy.push(data_flag.map(el=>el[0] + '<-[data]->' + String(el[1])).join(';'));
- }
- return token_map.get(data) + '<-[data]->' + JSON.stringify(copy_map.get(data));
- }
- mtec.parseJson = function(json_string){
- let token: string;
- let data: any;
- if(json_string.includes('<-[data]->')) [token, json_string] = json_string.replace('<-[data]->', '->[data]<-').split('->[data]<-');
- try{
- data = JSON.parse(json_string);
- }catch(err){
- data = json_string;
- }
- if(typeof data != 'object') return data;
- let data_map: Map<string,any> = new Map();
- data_map.set(token, data);
- let data_list = [data];
- for(let i = 0; i < data_list.length; i++){
- let item = data_list[i];
- if(Array.isArray(item)){
- if(typeof item.lastElement == 'string' && item.lastElement.includes('<-[data]->')){
- (item.pop() as string).split(';').map(item=>{
- let [token, index] = item.split('<-[data]->');
- return [token, Number(index)] as [string, number];
- }).forEach(el=>data_map.set(el[0], item[el[1]]));
- }
- item.forEach((el, i, arr)=>{
- if(typeof el == 'string' && el.includes('<-[ref]->')){
- let token = el.replace('<-[ref]->', '');
- arr[i] = data_map.get(token);
- }else if(typeof el == 'object') data_list.push(el);
- });
- }else if(item != null){
- Reflect.ownKeys(item).forEach(key=>{
- let value = Reflect.get(item, key);
- if(typeof value == 'object') data_list.push(value);
- else if(typeof value == 'string' && value.includes('<-[ref]->')){
- let token = value.replace('<-[ref]->', '');
- value = data_map.get(token);
- Reflect.set(item, key, value);
- }
- if(typeof key == 'string' && key.includes('<-[data]->')){
- Reflect.deleteProperty(item, key);
- let [token, k] = key.split('<-[data]->');
- Reflect.set(item, k, value);
- data_map.set(token, value);
- }
- });
- }
- }
- return data;
- }
- mtec.string.random = function(len, radix){
- [len, radix] = [[Number(len), 6], [Number(radix), 10]].map(_=>isNaN(_[0]) ? _[1] : _[0]);
- radix = Math.max(2, Math.min(36, radix));
- let str = Math.random().toString(radix).slice(2, 2+len);
- while(str.length < len){
- str += Math.random().toString(radix).slice(2, 2+len-str.length);
- }
- return str;
- }
- mtec.string.randomToken = function(len, radix, verify){
- [radix, verify] = mtec.pickValueByType([radix, verify], [['number', 10], ['function', undefined]]) as [number, (token: string)=>boolean];
- let token = mtec.string.random(len, radix);
- if(typeof verify == 'function'){
- while(!verify(token)){
- token = mtec.string.random(len, radix);
- }
- }
- return token;
- }
- mtec.string.getAffix = function(list){
- if(!list || list.length==0) return {prefix: '', suffix: '', max_length: 0};
- let prefix = list[0];
- let suffix = list[0];
- let pre_end = prefix.length;
- let suf_start = 0;
- let max_length = 0;
- list.forEach(el=>{
- if(el.length>max_length) max_length = el.length;
- if(!el.includes(prefix)){
- while(pre_end>0 && !el.includes(prefix.slice(0, pre_end))) pre_end--;
- prefix = prefix.slice(0, pre_end);
- }
- if(!el.includes(suffix)){
- while(suf_start<suffix.length-1 && !el.includes(suffix.slice(suf_start, suffix.length))) suf_start++;
- suffix = suffix.slice(suf_start, suffix.length);
- }
- });
- return {prefix, suffix, max_length};
- }
- mtec.string.normalLen = function(value, len){
- value = typeof value == 'string' ? value : String(value);
- value = '_'+value;
- return value.padEnd(len+1, '_');
- }
- mtec.string.levenshtein = function(a, b){
- const matrix: number[][] = [];
- let i: number;
- let j: number;
- for(i = 0; i <= a.length; i++) matrix[i] = [i];
- for(j = 0; j <= b.length; j++) matrix[0][j] = j;
- for(i = 1; i <= a.length; i++){
- for(j = 1; j <= b.length; j++){
- if(b.charAt(j-1) == a.charAt(i-1)) matrix[i][j] = matrix[i-1][j-1];
- else{
- matrix[i][j] = Math.min(
- matrix[i-1][j],
- matrix[i][j-1],
- matrix[i-1][j-1]
- ) + 1;
- }
- }
- }
- return matrix[a.length][b.length];
- }
- mtec.string.findLikeStr = function(target, list){
- let mostSimilar = list[0];
- let minDistance = mtec.string.levenshtein(mostSimilar, target);
- for (const str of list) {
- if (str === target) {
- return str;
- }
- const distance = mtec.string.levenshtein(str, target);
- if (distance < minDistance) {
- minDistance = distance;
- mostSimilar = str;
- }
- }
- return mostSimilar;
- }
- mtec.number.PI = Math.PI;
- mtec.number.RAD = Math.PI / 180;
- mtec.number.DEG = 180 / Math.PI;
- mtec.number.inRange = function(num, a, b){
- [num, a, b] = [num, a, b].map(_=>Number(_));
- if([num, a, b].includes(NaN)) return false;
- return num <= Math.max(a, b) && num >= Math.min(a, b);
- }
- mtec.number.getPrecision = function(num){
- num = Number(num);
- if(isNaN(num) || Number.isInteger(num)) return 0;
- return (num % 1).toString().length - (num>=0 ? 2 : 3);
- }
- mtec.number.repair = function(num){
- num = Number(num);
- if(isNaN(num)) return 0;
- if(Number.isInteger(num)) return num;
- let str = num.toString();
- if(str.length-str.indexOf('.') < 17) return num;
- let index = str.length-1;
- if(str[index]=='9') while(str[index]=='9') index--;
- else{
- index--;
- while(str[index]=='0') index--;
- }
- let weight = 10 ** (index-str.indexOf('.'));
- return Math.round(num * weight) / weight;
- }
- mtec.number.random = function(a, b, precision){
- [a, b] = [a, b].map(_=>{
- _ = Number(_);
- return isNaN(_) ? 0 : _;
- });
- let range = b-a;
- if(precision==undefined){
- if(Math.abs(range)==1) precision = 2;
- else if(!Number.isInteger(range)){
- range = mtec.number.repair(range);
- precision = mtec.number.getPrecision(range);
- if(range == 10 ** -precision) precision += 2;
- }else precision = 0;
- }
- let weight = 10 ** precision;
- return mtec.number.repair(a + Math.round(Math.random() * range * weight) / weight);
- }
- mtec.number.parse = function(value, spare){
- [spare, value] = [spare, value].map(_=>typeof _=='number' ? _ : Number(_));
- return isNaN(value) ? isNaN(spare) ? 0 : spare : value;
- }
- mtec.number.fixedNum = function(num, place, floor){
- let weight = 10 ** Math.round(mtec.number.parse(place));
- num = num * weight;
- num = floor===true ? Math.floor(num) : floor===false ? Math.ceil(num) : Math.round(num);
- return mtec.number.repair(num / weight);
- };
- mtec.number.limit = function(num, a, b){
- [num, a, b] = [num, a, b].map(_=>mtec.number.parse(_, 0));
- return Math.max(Math.min(a, b), Math.min(Math.max(a, b), num));
- };
- mtec.array.random = function(list){
- if(!Array.isArray(list)) return list;
- if(list.length==0) return undefined;
- if(list.length==1) return list[0];
- return list[Math.floor(Math.random() * list.length)];
- }
- //@ts-ignore
- mtec.array.randomeElement = function(list, len, repetition){
- len = len ?? 1;
- if(repetition===false) len = Math.min(len, list.length);
- repetition = repetition ?? len>list.length;
- let index_list: number[] = [];
- while(index_list.length < len){
- let index = mtec.number.random(0, list.length-1);
- if(!repetition) while(index_list.includes(index)) index = mtec.number.random(0, list.length-1);
- index_list.push(index);
- }
- return index_list.map(index=>list[index]);
- }
- mtec.array.last = function(list, index){
- if(!Array.isArray(list)) return list;
- if(list.length==0) return undefined;
- if(index){
- index = Number(index);
- index = Math.floor(isNaN(index) ? 0 : index) + 1;
- index = Math.max(1, Math.min(list.length, index));
- }else index = 1;
- return list[list.length-index];
- }
- //@ts-ignore
- mtec.array.clear = function(list){
- return (Array.isArray(list) && list.length>0) ? list.splice(0, list.length) : [];
- }
- mtec.array.remove = function(arr: any[], element: any, head?: boolean){
- let verify: (el: any, i: number, arr: any[])=>boolean;
- if(element instanceof Function) verify = element;
- else verify = (el: any, i: number, arr: any[])=>el==element;
- let [point, end, direction] = (head??true) ? [0, arr.length, 1] : [arr.length-1, -1, -1];
- while(point!=end){
- if(verify(arr[point], point, arr)) break;
- point += direction;
- }
- return point.inRange(0, arr.length-1) ? arr.splice(point, 1)[0] : undefined;
- }
- mtec.array.create = function(size, call){
- return new Array(size).fill(null, 0, size).map((_, i)=>call(i));
- }
- mtec.color.common = { aliceblue: '#f0f8ff', antiquewhite: '#faebd7', aqua: '#00ffff', aquamarine: '#7fffd4', azure: '#f0ffff', beige: '#f5f5dc', bisque: '#ffe4c4', black: '#000000', blanchedalmond: '#ffebcd', blue: '#0000ff', blueviolet: '#8a2be2', brown: '#a52a2a', burlywood: '#deb887', cadetblue: '#5f9ea0', chartreuse: '#7fff00', chocolate: '#d2691e', coral: '#ff7f50', cornflowerblue: '#6495ed', cornsilk: '#fff8dc', crimson: '#dc143c', cyan: '#00ffff', darkblue: '#00008b', darkcyan: '#008b8b', darkgoldenrod: '#b8860b', darkgray: '#a9a9a9', darkgreen: '#006400', darkkhaki: '#bdb76b', darkmagenta: '#8b008b', darkolivegreen: '#556b2f', darkorange: '#ff8c00', darkorchid: '#9932cc', darkred: '#8b0000', darksalmon: '#e9967a', darkseagreen: '#8fbc8f', darkslateblue: '#483d8b', darkslategray: '#2f4f4f', darkturquoise: '#00ced1', darkviolet: '#9400d3', deeppink: '#ff1493', deepskyblue: '#00bfff', dimgray: '#696969', dodgerblue: '#1e90ff', firebrick: '#b22222', floralwhite: '#fffaf0', forestgreen: '#228b22', fuchsia: '#ff00ff', gainsboro: '#dcdcdc', ghostwhite: '#f8f8ff', gold: '#ffd700', goldenrod: '#daa520', gray: '#808080', green: '#008000', greenyellow: '#adff2f', honeydew: '#f0fff0', hotpink: '#ff69b4', indianred: '#cd5c5c', indigo: '#4b0082', ivory: '#fffff0', khaki: '#f0e68c', lavender: '#e6e6fa', lavenderblush: '#fff0f5', lawngreen: '#7cfc00', lemonchiffon: '#fffacd', lightblue: '#add8e6', lightcoral: '#f08080', lightcyan: '#e0ffff', lightgoldenrodyellow: '#fafad2', lightgray: '#d3d3d3', lightgreen: '#90ee90', lightpink: '#ffb6c1', lightsalmon: '#ffa07a', lightseagreen: '#20b2aa', lightskyblue: '#87cefa', lightslategray: '#778899', lightsteelblue: '#b0c4de', lightyellow: '#ffffe0', lime: '#00ff00', limegreen: '#32cd32', linen: '#faf0e6', magenta: '#ff00ff', maroon: '#800000', mediumaquamarine: '#66cdaa', mediumblue: '#0000cd', mediumorchid: '#ba55d3', mediumpurple: '#9370db', mediumseagreen: '#3cb371', mediumslateblue: '#7b68ee', mediumspringgreen: '#00fa9a', mediumturquoise: '#48d1cc', mediumvioletred: '#c71585', midnightblue: '#191970', mintcream: '#f5fffa', mistyrose: '#ffe4e1', moccasin: '#ffe4b5', navajowhite: '#ffdead', navy: '#000080', oldlace: '#fdf5e6', olive: '#808000', olivedrab: '#6b8e23', orange: '#ffa500', orangered: '#ff4500', orchid: '#da70d6', palegoldenrod: '#eee8aa', palegreen: '#98fb98', paleturquoise: '#afeeee', palevioletred: '#db7093', papayawhip: '#ffefd5', peachpuff: '#ffdab9', peru: '#cd853f', pink: '#ffc0cb', plum: '#dda0dd', powderblue: '#b0e0e6', purple: '#800080', rebeccapurple: '#663399', red: '#ff0000', rosybrown: '#bc8f8f', royalblue: '#4169e1', saddlebrown: '#8b4513', salmon: '#fa8072', sandybrown: '#f4a460', seagreen: '#2e8b57', seashell: '#fff5ee', sienna: '#a0522d', silver: '#c0c0c0', skyblue: '#87ceeb', slateblue: '#6a5acd', slategray: '#708090', snow: '#fffafa', springgreen: '#00ff7f', steelblue: '#4682b4', tan: '#d2b48c', teal: '#008080', thistle: '#d8bfd8', tomato: '#ff6347', turquoise: '#40e0d0', violet: '#ee82ee', wheat: '#f5deb3', white: '#ffffff', whitesmoke: '#f5f5f5', yellow: '#ffff00', yellowgreen: '#9acd32', };
- mtec.color.toHexColor = function(color){
- let hex: string;
- if(color.startsWith('#')) hex = color.slice(1, 7);
- else if(!isNaN(Number('0x'+color))) hex = color.slice(0, 6);
- if(hex && [3, 4, 6, 8].includes(hex.length)) return mtec.color.normalizeHexColor('#' + hex);
- color = color.toLowerCase();
- color = Reflect.has(mtec.color.common, color) ? color : 'white';
- return Reflect.get(mtec.color.common, color);
- }
- mtec.color.normalizeHexColor = function(color){
- let hex: string;
- if(color.startsWith('#') && !isNaN(Number('0x'+color.slice(1, color.length)))) hex = color.replace('#', '');
- else hex = mtec.color.toHexColor(color).replace('#', '');
- if([3, 4].includes(hex.length)) hex = hex.split('').map(bit=>bit+bit).join('');
- if(hex.length>6) hex = hex.substring(0, 6);
- else hex.padEnd(6, '0');
- return '#' + hex.toUpperCase();
- }
- mtec.color.toRGBColor = function(color){
- let hex = mtec.color.normalizeHexColor(color);
- let [r, g, b] = hex.slice(1, hex.length).match(/.{1,2}/g).map(c=>parseInt(c, 16));
- return [r, g, b];
- }
- mtec.color.toHSLColor = function(color){
- let [r, g, b] = mtec.color.toRGBColor(color);
- let max = Math.max(r, g, b);
- let min = Math.min(r, g, b);
- let h, s, l = (max + min) / 2;
- if (max === min) {
- // 如果最大值和最小值相等,表示颜色是灰度的,色相设为0
- h = s = 0;
- } else {
- let d = max - min;
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
- switch (max) {
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
- case g: h = (b - r) / d + 2; break;
- case b: h = (r - g) / d + 4; break;
- }
- h /= 6;
- }
- return [h * 360, s * 100, l * 100].map(v=>Math.round(v)) as [number, number, number];
- }
- mtec.color.RGB2Hex = function(r, g, b){
- return '#' + [r, g, b].map(v=>v.toString(16).padStart(2, '0')).join('');
- }
- mtec.color.HSL2Hex = function(h, s, l){
- h /= 360; // 将色相转换为 [0, 1] 范围
- s /= 100; // 将饱和度转换为 [0, 1] 范围
- l /= 100; // 将亮度转换为 [0, 1] 范围
- let r, g, b;
- if (s === 0) {
- r = g = b = l; // 如果饱和度为 0,则为灰度色
- } else {
- let hue2rgb = function hue2rgb(p, q, t) {
- if (t < 0) t += 1;
- if (t > 1) t -= 1;
- if (t < 1 / 6) return p + (q - p) * 6 * t;
- if (t < 1 / 2) return q;
- if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
- return p;
- };
- let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- let p = 2 * l - q;
- r = hue2rgb(p, q, h + 1 / 3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1 / 3);
- }
- // 将 [0, 1] 范围的 RGB 值转换为 [0, 255] 范围并四舍五入
- r = Math.round(r * 255);
- g = Math.round(g * 255);
- b = Math.round(b * 255);
- return mtec.color.RGB2Hex(r, g, b);
- }
- mtec.color.logColorLike = function(cut){
- let list = Reflect.ownKeys(mtec.color.common).filter((color: string)=>color.includes(cut??'')) as string[];
- if(list.length<=0) return void 0;
- let format_str = '';
- let style_list = [];
- let default_style = 'padding: 0 0.5em; font-weight: bolder;';
- let start_style = 'border-top-left-radius: 0.5em 0.5em; border-bottom-left-radius: 0.5em 0.5em;';
- let end_style = 'border-top-right-radius: 0.5em 0.5em; border-bottom-right-radius: 0.5em 0.5em;';
- list.forEach(color=>{
- let hex = mtec.color.normalizeHexColor(Reflect.get(mtec.color.common, color));
- let [h, s, l] = mtec.color.toHSLColor(hex);
- format_str += '%c' + color + '%c' + hex;
- let font_color = mtec.color.HSL2Hex(h, s>0 ? 100 : 0, l>50 ? 20 : 80);
- let style_desc = [
- ['background-color', hex],
- ['color', font_color]
- ].map(item=>item.join(':')).join(';') + ';';
- let style_real = [
- ['background-color', hex],
- ['color', font_color]
- ].map(item=>item.join(':')).join(';') + ';';
- style_list.push(...[start_style + style_desc, style_real + end_style].map(s=>s+default_style));
- });
- console.log(format_str, ...style_list);
- }
- mtec.color.logFullColorLine = function(size){
- size = size??3;
- let format_str = '';
- let style_list = [];
- let default_style = 'font-weight: lighter; line-height: 5px; font-size: ' + size + 'px;';
- for(let i = 0; i < 360; i++){
- format_str += '%c ';
- style_list.push(default_style + 'background-color: ' + mtec.color.HSL2Hex(i, 100, 50));
- }
- console.log(format_str, ...style_list);
- }
- mtec.log.tag = function(tag, ...args){
- //return void 0;
- let str = '', colors = [];
- if(typeof(tag)=='string' && tag.includes(':')){
- tag.split(';').map(s=>{
- s = s.trim();
- if(s.length==0) return [];
- else return s.split(':').map(kv=>kv.trim());
- }).filter(item=>item.length==2 && item.every(kv=>kv.length>0))
- .forEach(item=>{
- str += '%c' + item[0];
- let [h, s, l] = mtec.color.toHSLColor(item[1]);
- let clr = [
- ['background-color', mtec.color.normalizeHexColor(item[1])],
- ['color', mtec.color.HSL2Hex(h, s>0 ? 100 : 0, l>50 ? 20 : 80)]
- ].reduce((t, el)=>{
- t.push(el.join(':'));
- return t;
- }, [
- 'padding:0 0.5em',
- 'font-weight: bolder',
- ]).join('; ') + '; ';
- colors.push(clr);
- });
- }
- colors[0] += 'border-top-left-radius: 0.5em 0.5em; border-bottom-left-radius: 0.5em 0.5em; ';
- colors[colors.length-1] += 'border-top-right-radius: 0.5em 0.5em; border-bottom-right-radius: 0.5em 0.5em; ';
- console.groupCollapsed(str + '%c', ...colors, '', ...args);
- console.trace();
- console.groupEnd();
- }
- mtec.log.warn = function(...args){
- mtec.log.tag("WARN:orange;>>:tomato", ...args);
- }
- mtec.local.read = function(key, out){
- let data_json = localStorage.getItem(key.encodeBtoA);
- if(data_json){
- data_json = data_json.decodeAtoB;
- if(out) mtec.fusionData(out, JSON.parse(data_json));
- else out = JSON.parse(data_json);
- }
- return out as any;
- }
- mtec.local.save = function(key, data){
- localStorage.setItem(key.encodeBtoA, JSON.stringify(data).encodeBtoA);
- }
- mtec.time.ONE_DAY = 24 * 60 * 60 * 1000;
- mtec.time.sameDay = function(d1, d2){
- if ([d1, d2].includes(undefined)) return false;
- let [day1, day2] = [d1, d2].map(d => new Date(d));
- return day1.toDateString() === day2.toDateString();
- };
|