PeriodData.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. export enum PeriodDataUpdate {
  2. none = 0,
  3. day = 1,
  4. week = 2,
  5. month = 3,
  6. }
  7. /**周期数据
  8. * @param T 为一个枚举类型
  9. * @param update PeriodDataUpdate 更新周期
  10. * @param limt 限制值最大,最小
  11. * 调用check检测更新
  12. * @exampl
  13. 定义数据枚举 字段名和字段key需要一致
  14. export enum day_type{
  15. score ="score",
  16. level ="level",
  17. relive="relive",
  18. }
  19. 初始所有定义数据
  20. day_data = new PeriodData<day_type>(PeriodDataUpdate.day,
  21. Object.keys(day_type) as day_type[],
  22. new Map([
  23. [day_type.relive,{min:0,max:3}],//限制每日复活3次
  24. ])
  25. );
  26. day_data.get(day_type.score)...
  27. */
  28. export default class PeriodData<T extends string | number | symbol> {
  29. private _data: Map<T, { v: number, min: number | null, max: number | null }> = new Map();
  30. private _data_Array: Map<T, boolean[]> = new Map();
  31. private _last: number = 0;
  32. private _update: PeriodDataUpdate;
  33. constructor(update: PeriodDataUpdate, limt?: Map<T, { min?: number | null, max?: number | null }>) {
  34. this._update = update;
  35. if (!limt) return;
  36. //遍历所有键进行初始化
  37. limt.forEach((v, key) => {
  38. this._data.set(key, { v: v.min ?? 0, min: v.min, max: v.max });
  39. }, this);
  40. }
  41. /**
  42. * 序列化(数据库存储)
  43. */
  44. public serialize(): any {
  45. const obj: { [key: string]: number } = {};
  46. this._data.forEach((value, key) => { obj[String(key)] = value.v; });
  47. const obj1: { [key: string]: any } = {};
  48. this._data_Array.forEach((value, key) => { obj1[String(key)] = value; });
  49. const data = {
  50. "last": this._last,
  51. "data": obj,
  52. "data_Array": obj1
  53. };
  54. return data;
  55. }
  56. /**
  57. * 反序列化
  58. */
  59. public unserialize(data: any): void {
  60. if (!data) return;
  61. this._last = data.last ?? 0;
  62. const obj: { [key: string]: number } = data.data;
  63. if (obj) {
  64. for (const key in obj) {
  65. const value = obj[key];
  66. this._get(key as T).v = value;
  67. }
  68. }
  69. const obj1: { [key: string]: any } = data.data_Array;
  70. if (obj1) {
  71. for (const key in obj1) {
  72. const value = obj1[key];
  73. this.set_Array(key as T, value);
  74. }
  75. }
  76. }
  77. private _get(key: T): { v: number, min: number, max: number } {
  78. let data = this._data.get(key);
  79. if (!data) {
  80. data = { v: 0, min: 0, max: null };
  81. this._data.set(key, data);
  82. }
  83. return data;
  84. }
  85. private _get_Array(key: T): boolean[] {
  86. let data = this._data_Array.get(key);
  87. console.log(`_get_Array called with key: `+String(key)+ `data:`, data); // 输出存储的数据
  88. if (!data) {
  89. data = new Array(5).fill(false);
  90. this._data_Array.set(key, data);
  91. }
  92. return data;
  93. }
  94. /**如果有必要,重新设置数据的min,max*/
  95. set(key: T, value: number, min?: number | null, max?: number | null) {
  96. const d = this._get(key);
  97. d.v = value;
  98. d.min = min;
  99. d.max = max;
  100. }
  101. /**获取数据*/
  102. get(key: T): number {
  103. return this._get(key).v;
  104. }
  105. set_Array(key: T, value: any) {
  106. this._data_Array.set(key, value);
  107. }
  108. /**获取数据*/
  109. get_Array(key: T): boolean[] {
  110. return this._get_Array(key);
  111. }
  112. /**有大最值的话,获取数据为剩余可用次数*/
  113. get_available(key: T): number {
  114. const d = this._get(key);
  115. if (d.max) return d.max - d.v;
  116. return d.v;
  117. }
  118. isEnble(key: T): boolean {
  119. const d = this._get(key);
  120. return d.v > 0;
  121. }
  122. enble(key: T): void {
  123. this._get(key).v = 1;
  124. }
  125. disEnble(key: T): void {
  126. this._get(key).v = 0;
  127. }
  128. /**增加数据的值*/
  129. add(key: T, n: number = 1): number | null {
  130. return this.change(key, n);
  131. }
  132. /**减小数据的值*/
  133. sub(key: T, n: number = 1): number | null {
  134. return this.change(key, -n);
  135. }
  136. /**改变数据 n>0增加 小于0减少*/
  137. change(key: T, n: number): number | null {
  138. const d = this._get(key);
  139. if (!d) return null;
  140. d.v += n;
  141. if (d.min && d.v < d.min) d.v = d.min;
  142. if (d.max && d.v > d.max) d.v = d.max;
  143. return d.v;
  144. }
  145. /**改变数据,比原本值大直接替换,没有改变返回null*/
  146. change_big(key: T, n: number): number | null {
  147. const d = this._get(key);
  148. if (!d) return null;
  149. if (n > d.v) {
  150. d.v = n;
  151. if (d.min && d.v < d.min) d.v = d.min;
  152. if (d.max && d.v > d.max) d.v = d.max;
  153. return d.v;
  154. }
  155. return null;
  156. }
  157. /**改变数据,比原本值小直接替换,没有改变返回null*/
  158. change_sm(key: T, n: number): number | null {
  159. const d = this._get(key);
  160. if (!d) return null;
  161. if (n < d.v) {
  162. d.v = n;
  163. if (d.min && d.v < d.min) d.v = d.min;
  164. if (d.max && d.v > d.max) d.v = d.max;
  165. return d.v;
  166. }
  167. return null;
  168. }
  169. /**检测更新now当前时间戳(ms)*/
  170. check(now: number): boolean {
  171. if (this._update == PeriodDataUpdate.none) return false;
  172. if (this._update == PeriodDataUpdate.day) {
  173. if (!this.isSameDate(now, this._last)) {
  174. this._last = now;
  175. this.reset();
  176. return true;
  177. }
  178. }
  179. if (this._update == PeriodDataUpdate.week) {
  180. if (!this.areDatesInSameWeek(now, this._last)) {
  181. this._last = now;
  182. this.reset();
  183. this._data_Array=new Map();
  184. return true;
  185. }
  186. }
  187. if (this._update == PeriodDataUpdate.month) {
  188. if (!this.areDatesInSameMonth(now, this._last)) {
  189. this._last = now;
  190. this.reset();
  191. return true;
  192. }
  193. }
  194. return false;
  195. }
  196. reset(): void {
  197. for (const key of this._data.keys()) {
  198. const data = this._get(key);
  199. data.v = data.min ?? 0;
  200. }
  201. for(const key of this._data_Array.keys()){
  202. this._data_Array.set(key,new Array(5).fill(false));
  203. }
  204. }
  205. /**判定两个时间是否是同一天*/
  206. private isSameDate(timestamp1: number, timestamp2: number): boolean {
  207. let date1 = new Date(timestamp1); let date2 = new Date(timestamp2);
  208. return date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate();
  209. }
  210. /**判定两个时间是否是同一周*/
  211. private areDatesInSameWeek(date1: number, date2: number): boolean {
  212. const startOfWeek1 = this.getStartOfWeek(new Date(date1));
  213. const startOfWeek2 = this.getStartOfWeek(new Date(date2));
  214. return startOfWeek1.getTime() === startOfWeek2.getTime();
  215. }
  216. private getStartOfWeek(date: Date): Date {
  217. const startOfWeek = new Date(date);
  218. const day = startOfWeek.getDay(); // 星期日是 0,星期一是 1,依此类推
  219. const diff = startOfWeek.getDate() - day; // 计算当前日期所在周的第一天
  220. startOfWeek.setDate(diff); // 设置为该周的第一天
  221. startOfWeek.setHours(0, 0, 0, 0); // 设置时间为 00:00:00
  222. return startOfWeek;
  223. }
  224. private areDatesInSameMonth(date1: number, date2: number): boolean {
  225. const d1 = new Date(date1);
  226. const d2 = new Date(date2);
  227. return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth();
  228. }
  229. }