123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- export enum PeriodDataUpdate {
- none = 0,
- day = 1,
- week = 2,
- month = 3,
- }
- /**周期数据
- * @param T 为一个枚举类型
- * @param update PeriodDataUpdate 更新周期
- * @param limt 限制值最大,最小
- * 调用check检测更新
- * @exampl
- 定义数据枚举 字段名和字段key需要一致
- export enum day_type{
- score ="score",
- level ="level",
- relive="relive",
- }
- 初始所有定义数据
- day_data = new PeriodData<day_type>(PeriodDataUpdate.day,
- Object.keys(day_type) as day_type[],
- new Map([
- [day_type.relive,{min:0,max:3}],//限制每日复活3次
- ])
- );
- day_data.get(day_type.score)...
- */
- export default class PeriodData<T extends string | number | symbol> {
- private _data: Map<T, { v: number, min: number | null, max: number | null }> = new Map();
- private _data_Array: Map<T, boolean[]> = new Map();
- private _last: number = 0;
- private _update: PeriodDataUpdate;
- constructor(update: PeriodDataUpdate, limt?: Map<T, { min?: number | null, max?: number | null }>) {
- this._update = update;
- if (!limt) return;
- //遍历所有键进行初始化
- limt.forEach((v, key) => {
- this._data.set(key, { v: v.min ?? 0, min: v.min, max: v.max });
- }, this);
- }
- /**
- * 序列化(数据库存储)
- */
- public serialize(): any {
- const obj: { [key: string]: number } = {};
- this._data.forEach((value, key) => { obj[String(key)] = value.v; });
- const obj1: { [key: string]: any } = {};
- this._data_Array.forEach((value, key) => { obj1[String(key)] = value; });
- const data = {
- "last": this._last,
- "data": obj,
- "data_Array": obj1
- };
- return data;
- }
- /**
- * 反序列化
- */
- public unserialize(data: any): void {
- if (!data) return;
- this._last = data.last ?? 0;
- const obj: { [key: string]: number } = data.data;
- if (obj) {
- for (const key in obj) {
- const value = obj[key];
- this._get(key as T).v = value;
- }
- }
- const obj1: { [key: string]: any } = data.data_Array;
- if (obj1) {
- for (const key in obj1) {
- const value = obj1[key];
- this.set_Array(key as T, value);
- }
- }
- }
- private _get(key: T): { v: number, min: number, max: number } {
- let data = this._data.get(key);
- if (!data) {
- data = { v: 0, min: 0, max: null };
- this._data.set(key, data);
- }
- return data;
- }
- private _get_Array(key: T): boolean[] {
- let data = this._data_Array.get(key);
- console.log(`_get_Array called with key: `+String(key)+ `data:`, data); // 输出存储的数据
- if (!data) {
- data = new Array(5).fill(false);
- this._data_Array.set(key, data);
- }
- return data;
- }
- /**如果有必要,重新设置数据的min,max*/
- set(key: T, value: number, min?: number | null, max?: number | null) {
- const d = this._get(key);
- d.v = value;
- d.min = min;
- d.max = max;
- }
- /**获取数据*/
- get(key: T): number {
- return this._get(key).v;
- }
- set_Array(key: T, value: any) {
- this._data_Array.set(key, value);
- }
- /**获取数据*/
- get_Array(key: T): boolean[] {
- return this._get_Array(key);
- }
- /**有大最值的话,获取数据为剩余可用次数*/
- get_available(key: T): number {
- const d = this._get(key);
- if (d.max) return d.max - d.v;
- return d.v;
- }
- isEnble(key: T): boolean {
- const d = this._get(key);
- return d.v > 0;
- }
- enble(key: T): void {
- this._get(key).v = 1;
- }
- disEnble(key: T): void {
- this._get(key).v = 0;
- }
- /**增加数据的值*/
- add(key: T, n: number = 1): number | null {
- return this.change(key, n);
- }
- /**减小数据的值*/
- sub(key: T, n: number = 1): number | null {
- return this.change(key, -n);
- }
- /**改变数据 n>0增加 小于0减少*/
- change(key: T, n: number): number | null {
- const d = this._get(key);
- if (!d) return null;
- d.v += n;
- if (d.min && d.v < d.min) d.v = d.min;
- if (d.max && d.v > d.max) d.v = d.max;
- return d.v;
- }
- /**改变数据,比原本值大直接替换,没有改变返回null*/
- change_big(key: T, n: number): number | null {
- const d = this._get(key);
- if (!d) return null;
- if (n > d.v) {
- d.v = n;
- if (d.min && d.v < d.min) d.v = d.min;
- if (d.max && d.v > d.max) d.v = d.max;
- return d.v;
- }
- return null;
- }
- /**改变数据,比原本值小直接替换,没有改变返回null*/
- change_sm(key: T, n: number): number | null {
- const d = this._get(key);
- if (!d) return null;
- if (n < d.v) {
- d.v = n;
- if (d.min && d.v < d.min) d.v = d.min;
- if (d.max && d.v > d.max) d.v = d.max;
- return d.v;
- }
- return null;
- }
- /**检测更新now当前时间戳(ms)*/
- check(now: number): boolean {
- if (this._update == PeriodDataUpdate.none) return false;
- if (this._update == PeriodDataUpdate.day) {
- if (!this.isSameDate(now, this._last)) {
- this._last = now;
- this.reset();
- return true;
- }
- }
- if (this._update == PeriodDataUpdate.week) {
- if (!this.areDatesInSameWeek(now, this._last)) {
- this._last = now;
- this.reset();
- this._data_Array=new Map();
- return true;
- }
- }
- if (this._update == PeriodDataUpdate.month) {
- if (!this.areDatesInSameMonth(now, this._last)) {
- this._last = now;
- this.reset();
- return true;
- }
- }
- return false;
- }
- reset(): void {
- for (const key of this._data.keys()) {
- const data = this._get(key);
- data.v = data.min ?? 0;
- }
- for(const key of this._data_Array.keys()){
- this._data_Array.set(key,new Array(5).fill(false));
- }
- }
- /**判定两个时间是否是同一天*/
- private isSameDate(timestamp1: number, timestamp2: number): boolean {
- let date1 = new Date(timestamp1); let date2 = new Date(timestamp2);
- return date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate();
- }
- /**判定两个时间是否是同一周*/
- private areDatesInSameWeek(date1: number, date2: number): boolean {
- const startOfWeek1 = this.getStartOfWeek(new Date(date1));
- const startOfWeek2 = this.getStartOfWeek(new Date(date2));
- return startOfWeek1.getTime() === startOfWeek2.getTime();
- }
- private getStartOfWeek(date: Date): Date {
- const startOfWeek = new Date(date);
- const day = startOfWeek.getDay(); // 星期日是 0,星期一是 1,依此类推
- const diff = startOfWeek.getDate() - day; // 计算当前日期所在周的第一天
- startOfWeek.setDate(diff); // 设置为该周的第一天
- startOfWeek.setHours(0, 0, 0, 0); // 设置时间为 00:00:00
- return startOfWeek;
- }
- private areDatesInSameMonth(date1: number, date2: number): boolean {
- const d1 = new Date(date1);
- const d2 = new Date(date2);
- return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth();
- }
- }
|