PeriodData.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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, any> = 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): any {
  86. let data = this._data_Array.get(key);
  87. if (!data) {
  88. data = new Array(5).fill(false);
  89. this._data_Array.set(key, data);
  90. }
  91. return data;
  92. }
  93. /**如果有必要,重新设置数据的min,max*/
  94. set(key: T, value: number, min?: number | null, max?: number | null) {
  95. const d = this._get(key);
  96. d.v = value;
  97. d.min = min;
  98. d.max = max;
  99. }
  100. /**获取数据*/
  101. get(key: T): number {
  102. return this._get(key).v;
  103. }
  104. set_Array(key: T, value: any) {
  105. this._data_Array.set(key, value);
  106. }
  107. /**获取数据*/
  108. get_Array(key: T): any {
  109. return this._get_Array(key);
  110. }
  111. /**有大最值的话,获取数据为剩余可用次数*/
  112. get_available(key: T): number {
  113. const d = this._get(key);
  114. if (d.max) return d.max - d.v;
  115. return d.v;
  116. }
  117. isEnble(key: T): boolean {
  118. const d = this._get(key);
  119. return d.v > 0;
  120. }
  121. enble(key: T): void {
  122. this._get(key).v = 1;
  123. }
  124. disEnble(key: T): void {
  125. this._get(key).v = 0;
  126. }
  127. /**增加数据的值*/
  128. add(key: T, n: number = 1): number | null {
  129. return this.change(key, n);
  130. }
  131. /**减小数据的值*/
  132. sub(key: T, n: number = 1): number | null {
  133. return this.change(key, -n);
  134. }
  135. /**改变数据 n>0增加 小于0减少*/
  136. change(key: T, n: number): number | null {
  137. const d = this._get(key);
  138. if (!d) return null;
  139. d.v += n;
  140. if (d.min && d.v < d.min) d.v = d.min;
  141. if (d.max && d.v > d.max) d.v = d.max;
  142. return d.v;
  143. }
  144. /**改变数据,比原本值大直接替换,没有改变返回null*/
  145. change_big(key: T, n: number): number | null {
  146. const d = this._get(key);
  147. if (!d) return null;
  148. if (n > d.v) {
  149. d.v = n;
  150. if (d.min && d.v < d.min) d.v = d.min;
  151. if (d.max && d.v > d.max) d.v = d.max;
  152. return d.v;
  153. }
  154. return null;
  155. }
  156. /**改变数据,比原本值小直接替换,没有改变返回null*/
  157. change_sm(key: T, n: number): number | null {
  158. const d = this._get(key);
  159. if (!d) return null;
  160. if (n < d.v) {
  161. d.v = n;
  162. if (d.min && d.v < d.min) d.v = d.min;
  163. if (d.max && d.v > d.max) d.v = d.max;
  164. return d.v;
  165. }
  166. return null;
  167. }
  168. /**检测更新now当前时间戳(ms)*/
  169. check(now: number): boolean {
  170. if (this._update == PeriodDataUpdate.none) return false;
  171. if (this._update == PeriodDataUpdate.day) {
  172. if (!this.isSameDate(now, this._last)) {
  173. this._last = now;
  174. this.reset();
  175. return true;
  176. }
  177. }
  178. if (this._update == PeriodDataUpdate.week) {
  179. if (!this.areDatesInSameWeek(now, this._last)) {
  180. this._last = now;
  181. this.reset();
  182. this._data_Array=new Map();
  183. return true;
  184. }
  185. }
  186. if (this._update == PeriodDataUpdate.month) {
  187. if (!this.areDatesInSameMonth(now, this._last)) {
  188. this._last = now;
  189. this.reset();
  190. return true;
  191. }
  192. }
  193. return false;
  194. }
  195. reset(): void {
  196. for (const key of this._data.keys()) {
  197. const data = this._get(key);
  198. data.v = data.min ?? 0;
  199. }
  200. }
  201. /**判定两个时间是否是同一天*/
  202. private isSameDate(timestamp1: number, timestamp2: number): boolean {
  203. let date1 = new Date(timestamp1); let date2 = new Date(timestamp2);
  204. return date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate();
  205. }
  206. /**判定两个时间是否是同一周*/
  207. private areDatesInSameWeek(date1: number, date2: number): boolean {
  208. const startOfWeek1 = this.getStartOfWeek(new Date(date1));
  209. const startOfWeek2 = this.getStartOfWeek(new Date(date2));
  210. return startOfWeek1.getTime() === startOfWeek2.getTime();
  211. }
  212. private getStartOfWeek(date: Date): Date {
  213. const startOfWeek = new Date(date);
  214. const day = startOfWeek.getDay(); // 星期日是 0,星期一是 1,依此类推
  215. const diff = startOfWeek.getDate() - day; // 计算当前日期所在周的第一天
  216. startOfWeek.setDate(diff); // 设置为该周的第一天
  217. startOfWeek.setHours(0, 0, 0, 0); // 设置时间为 00:00:00
  218. return startOfWeek;
  219. }
  220. private areDatesInSameMonth(date1: number, date2: number): boolean {
  221. const d1 = new Date(date1);
  222. const d2 = new Date(date2);
  223. return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth();
  224. }
  225. }