1// loading-manager.js - ããã°ã¬ãã·ããã¼ãã£ã³ã°ã管çããã¢ã¸ã¥ã¼ã« 2 3/** 4 * ããã°ã¬ãã·ããã¼ãã£ã³ã°ã管çããã¯ã©ã¹ 5 */ 6class LoadingManager { 7 constructor() { 8 this.loadingState = { 9 isLoading: true, 10 loadingProgress: 0, 11 isInitialDataLoaded: false, 12 loadingError: null, 13 cachedData: {} 14 }; 15 16 // ãã£ãã·ã¥ã®æå¹æéï¼24æéï¼ 17 this.CACHE_EXPIRY = 24 * 60 * 60 * 1000; 18 19 // ãã¼ã«ã«ã¹ãã¬ã¼ã¸ã®ãã¼ 20 this.STORAGE_KEYS = { 21 EVENT_LIST: 'rizin_event_list', 22 EVENT_DATA_PREFIX: 'rizin_event_data_', 23 LAST_UPDATE: 'rizin_last_update' 24 }; 25 } 26 27 /** 28 * ãã¼ãã£ã³ã°ç¶æ ãåå¾ 29 * @returns {Object} ãã¼ãã£ã³ã°ç¶æ 30 */ 31 getLoadingState() { 32 return this.loadingState; 33 } 34 35 /** 36 * ãã¼ãã£ã³ã°é²æãæ´æ° 37 * @param {number} progress - 鲿çï¼0-100ï¼ 38 */ 39 updateProgress(progress) { 40 this.loadingState.loadingProgress = Math.min(Math.max(0, progress), 100); 41 } 42 43 /** 44 * ãã£ãã·ã¥ãããã¼ã¿ãåå¾ 45 * @param {string} key - ãã£ãã·ã¥ãã¼ 46 * @returns {Object|null} ãã£ãã·ã¥ããããã¼ã¿ã¾ãã¯null 47 */ 48 getFromCache(key) { 49 try { 50 const cachedItem = localStorage.getItem(key); 51 if (!cachedItem) return null; 52 53 const { data, timestamp } = JSON.parse(cachedItem); 54 55 // ãã£ãã·ã¥ã®æå¹æéããã§ã㯠56 if (Date.now() - timestamp > this.CACHE_EXPIRY) { 57 localStorage.removeItem(key); 58 return null; 59 } 60 61 return data; 62 } catch (error) { 63 console.error('ãã£ãã·ã¥ããã®èªã¿è¾¼ã¿ã¨ã©ã¼:', error); 64 return null; 65 } 66 } 67 68 /** 69 * ãã¼ã¿ããã£ãã·ã¥ã«ä¿å 70 * @param {string} key - ãã£ãã·ã¥ãã¼ 71 * @param {Object} data - ä¿åãããã¼ã¿ 72 */ 73 saveToCache(key, data) { 74 try { 75 const cacheItem = { 76 data, 77 timestamp: Date.now() 78 }; 79 localStorage.setItem(key, JSON.stringify(cacheItem)); 80 } catch (error) { 81 console.error('ãã£ãã·ã¥ã¸ã®ä¿åã¨ã©ã¼:', error); 82 } 83 } 84 85 /** 86 * ã¤ãã³ããªã¹ããèªã¿è¾¼ãï¼ãã£ãã·ã¥ãªãï¼ 87 * @returns {Promise<Array>} ã¤ãã³ããªã¹ã 88 */ 89 async loadEventList() { 90 this.loadingState.isLoading = true; 91 this.updateProgress(5); 92 93 try { 94 // event-listã¯å¸¸ã«ææ°ãã¼ã¿ãåå¾ï¼ãã£ãã·ã¥ããªãï¼
95 console.log('ã¤ãã³ããªã¹ãèªã¿è¾¼ã¿éå§ï¼ãã£ãã·ã¥ãªãï¼'); 96 97 // ãã£ãã·ã¥ãã¹ãã£ã³ã°ç¨ã®ã¿ã¤ã ã¹ã¿ã³ãã追å 98 const timestamp = Date.now(); 99 const response = await fetch(`data/event-list.json?t=${timestamp}`, { 100 cache: 'no-cache', 101 headers: { 102 'Cache-Control': 'no-cache' 103 } 104 }); 105 106 if (!response.ok) { 107 throw new Error(`HTTP error! status: ${response.status}`); 108 } 109 110 const data = await response.json(); 111 console.log('ã¤ãã³ããªã¹ãèªã¿è¾¼ã¿æå:', data); 112 113 // ã¤ãã³ããªã¹ããå¦ç 114 let eventList = []; 115 116 if (data.events && Array.isArray(data.events)) { 117 console.log('eventsé åãæ¤åºãã¾ãã'); 118 eventList = data.events.map(event => ({ 119 id: event.filename.replace('.json', ''), 120 name: event.name, 121 date: event.date, 122 file: event.filename, 123 venue: event.venue, 124 status: event.status 125 })); 126 } else if (Array.isArray(data)) { 127 console.log('é åå½¢å¼ã®ã¤ãã³ããªã¹ããæ¤åºãã¾ãã'); 128 eventList = data.map(event => ({ 129 id: event.file.replace('.json', ''), 130 name: event.name, 131 date: event.date, 132 file: event.file, 133 status: event.status 134 })); 135 } else { 136 console.error('䏿ãªã¤ãã³ããªã¹ãå½¢å¼:', data); 137 throw new Error('䏿ãªã¤ãã³ããªã¹ãå½¢å¼'); 138 } 139 140 // ã¤ãã³ããªã¹ããæ¥ä»é ã«éé ã½ã¼ã 141 eventList.sort((a, b) => { 142 const dateA = new Date(a.date); 143 const dateB = new Date(b.date); 144 return dateB - dateA; 145 }); 146 147 // event-listã¯ãã£ãã·ã¥ããªãï¼å¸¸ã«ææ°ãã¼ã¿ãåå¾ããããï¼ 148 console.log('ã¤ãã³ããªã¹ãå¦çå®äº:', eventList.length, 'ä»¶'); 149 this.updateProgress(20); 150 151 return eventList; 152 } catch (error) { 153 console.error('ã¤ãã³ããªã¹ãèªã¿è¾¼ã¿ã¨ã©ã¼:', error); 154 this.loadingState.loadingError = 'ã¤ãã³ããªã¹ãã®èªã¿è¾¼ã¿ã«å¤±æãã¾ãã'; 155 throw error; 156 } 157 } 158 159 /** 160 * ææ°ã®ã¤ãã³ããã¼ã¿ãåªå çã«èªã¿è¾¼ãï¼ãã¤ããªãããã£ãã·ã¥ï¼ 161 * @param {Array} eventList - ã¤ãã³ããªã¹ã 162 * @param {number} count - èªã¿è¾¼ãã¤ãã³ãæ° 163 * @returns {Promise<Object>} èªã¿è¾¼ãã ã¤ãã³ããã¼ã¿ 164 */ 165 async loadPriorityEventData(eventList, count = 3) { 166 const priorityEvents = eventList.slice(0, count); 167 const eventData = {}; 168 169 for (let i = 0; i < priorityEvents.length; i++) { 170 const event = priorityEvents[i]; 171 try { 172 // ãã¤ããªãããã£ãã·ã¥æ¦ç¥ãä½¿ç¨ 173 const shouldUseCache = !this.shouldDisableCacheForEvent(event.date); 174 175 if (shouldUseCache) {
176 // å¤ãã¤ãã³ãã¯ãã£ãã·ã¥ããåå¾ã試ã¿ã 177 const cacheKey = `${this.STORAGE_KEYS.EVENT_DATA_PREFIX}${event.id}`; 178 const cachedData = this.getFromCache(cacheKey); 179 180 if (cachedData) { 181 console.log(`ãã£ãã·ã¥ããåå¾: ${event.file}`); 182 eventData[event.id] = cachedData; 183 } else { 184 // ãã£ãã·ã¥ã«ãªããã°æ°è¦åå¾ãã¦ãã£ãã·ã¥ã«ä¿å 185 const data = await this.fetchEventData(event.file, false, event.date); 186 eventData[event.id] = data; 187 this.saveToCache(cacheKey, data); 188 } 189 } else { 190 // ææ°ã¤ãã³ãã¯å¸¸ã«ææ°ãã¼ã¿ãåå¾ 191 console.log(`ææ°ãã¼ã¿åå¾: ${event.file}`); 192 const data = await this.fetchEventData(event.file, false, event.date); 193 eventData[event.id] = data; 194 } 195 196 // é²æãæ´æ°ï¼20%ãã50%ã¾ã§ï¼ 197 this.updateProgress(20 + Math.floor((i + 1) / priorityEvents.length * 30)); 198 } catch (error) { 199 console.error(`ã¤ãã³ããã¼ã¿ ${event.file} ã®èªã¿è¾¼ã¿ã«å¤±æãã¾ãã:`, error); 200 } 201 } 202 203 // åæãã¼ã¿èªã¿è¾¼ã¿å®äº 204 this.loadingState.isInitialDataLoaded = true; 205 206 return eventData; 207 } 208 209 /** 210 * æ®ãã®ã¤ãã³ããã¼ã¿ãããã¯ã°ã©ã¦ã³ãã§èªã¿è¾¼ãï¼ãã¤ããªãããã£ãã·ã¥ï¼ 211 * @param {Array} eventList - ã¤ãã³ããªã¹ã 212 * @param {number} startIndex - éå§ã¤ã³ããã¯ã¹ 213 * @returns {Promise<Object>} èªã¿è¾¼ãã ã¤ãã³ããã¼ã¿ 214 */ 215 async loadRemainingEventData(eventList, startIndex = 3) { 216 const remainingEvents = eventList.slice(startIndex); 217 const eventData = {}; 218 219 for (let i = 0; i < remainingEvents.length; i++) { 220 const event = remainingEvents[i]; 221 try { 222 // ãã¤ããªãããã£ãã·ã¥æ¦ç¥ãä½¿ç¨ 223 const shouldUseCache = !this.shouldDisableCacheForEvent(event.date); 224 225 if (shouldUseCache) {
226 // å¤ãã¤ãã³ãã¯ãã£ãã·ã¥ããåå¾ã試ã¿ã 227 const cacheKey = `${this.STORAGE_KEYS.EVENT_DATA_PREFIX}${event.id}`; 228 const cachedData = this.getFromCache(cacheKey); 229 230 if (cachedData) { 231 console.log(`ãã£ãã·ã¥ããåå¾: ${event.file}`); 232 eventData[event.id] = cachedData; 233 } else { 234 // ãã£ãã·ã¥ã«ãªããã°æ°è¦åå¾ãã¦ãã£ãã·ã¥ã«ä¿å 235 const data = await this.fetchEventData(event.file, false, event.date); 236 eventData[event.id] = data; 237 this.saveToCache(cacheKey, data); 238 } 239 } else { 240 // ææ°ã¤ãã³ãã¯å¸¸ã«ææ°ãã¼ã¿ãåå¾ 241 console.log(`ææ°ãã¼ã¿åå¾: ${event.file}`); 242 const data = await this.fetchEventData(event.file, false, event.date); 243 eventData[event.id] = data; 244 } 245 246 // é²æãæ´æ°ï¼50%ãã100%ã¾ã§ï¼ 247 this.updateProgress(50 + Math.floor((i + 1) / remainingEvents.length * 50)); 248 } catch (error) { 249 console.error(`ã¤ãã³ããã¼ã¿ ${event.file} ã®èªã¿è¾¼ã¿ã«å¤±æãã¾ãã:`, error); 250 } 251 } 252 253 // èªã¿è¾¼ã¿å®äº 254 this.loadingState.isLoading = false; 255 this.updateProgress(100); 256 257 return eventData; 258 } 259 260 /** 261 * ã¤ãã³ããã¼ã¿ãåå¾ 262 * @param {string} filename - ã¤ãã³ããã¡ã¤ã«å 263 * @param {boolean} forceRefresh - å¼·å¶çã«ææ°ãã¼ã¿ãåå¾ãããã©ãã 264 * @param {string} eventDate - ã¤ãã³ãæ¥ä»ï¼YYYY-MM-DDå½¢å¼ï¼ 265 * @returns {Promise<Object>} ã¤ãã³ããã¼ã¿ 266 */ 267 async fetchEventData(filename, forceRefresh = false, eventDate = null) {
268 console.log(`ã¤ãã³ããã¼ã¿èªã¿è¾¼ã¿éå§: ${filename}`); 269 270 // ææ°3ã¶æä»¥å ã®ã¤ãã³ãã¯ãã£ãã·ã¥ãç¡å¹å 271 const shouldDisableCache = this.shouldDisableCacheForEvent(eventDate); 272 const useNoCache = forceRefresh || shouldDisableCache; 273 274 let url = `data/${filename}`; 275 let fetchOptions = {}; 276 277 if (useNoCache) { 278 console.log(`ãã£ãã·ã¥ç¡å¹å: ${filename} (${shouldDisableCache ? 'ææ°ã¤ãã³ã' : 'å¼·å¶æ´æ°'})`); 279 const timestamp = Date.now(); 280 url += `?t=${timestamp}`; 281 fetchOptions = { 282 cache: 'no-cache', 283 headers: { 284 'Cache-Control': 'no-cache' 285 } 286 }; 287 } else { 288 console.log(`ãã£ãã·ã¥ä½¿ç¨: ${filename} (å¤ãã¤ãã³ã)`); 289 } 290 291 const response = await fetch(url, fetchOptions); 292 293 if (!response.ok) { 294 throw new Error(`HTTP error! status: ${response.status}`); 295 } 296 297 const eventData = await response.json(); 298 console.log('ã¤ãã³ããã¼ã¿èªã¿è¾¼ã¿æå:', eventData); 299 300 return eventData; 301 } 302 303 /** 304 * æå®ãã¡ã¤ã«ã®Last-Modifiedãåå¾ 305 * @param {string} url 306 * @returns {Promise<string|null>} 307 */ 308 async getLastModified(url) { 309 try { 310 console.log('HEADãªã¯ã¨ã¹ãéå§:', url); 311 const res = await fetch(url, { method: 'HEAD' }); 312 console.log('HEADãªã¯ã¨ã¹ãçµæ:', res.status, res.ok); 313 if (res.ok) { 314 const lastModified = res.headers.get('Last-Modified'); 315 console.log('Last-Modifiedãããã¼:', lastModified); 316 return lastModified; 317 } 318 } catch (e) { 319 console.warn('HEADãªã¯ã¨ã¹ã失æ:', url, e); 320 } 321 return null; 322 } 323 324 /** 325 * å·®ååå¾ä»ãã¤ãã³ããã¼ã¿åå¾ 326 * @param {string} eventId 327 * @param {string} filename 328 * @param {string} eventDate 329 * @returns {Promise<Object>} ã¤ãã³ããã¼ã¿ 330 */ 331 async fetchEventDataWithDiff(eventId, filename, eventDate = null) { 332 const url = `data/${filename}`; 333 const lastModified = await this.getLastModified(url); 334 const lmKey = `${eventId}_lastModified`; 335 const dataKey = `${eventId}_data`; 336 const prevLastModified = localStorage.getItem(lmKey); 337 let eventData = null; 338 if (lastModified && lastModified === prevLastModified) { 339 // 夿´ãªã: ãã£ãã·ã¥å©ç¨ 340 const cached = localStorage.getItem(dataKey); 341 if (cached) { 342 try { 343 eventData = JSON.parse(cached); 344 console.log('å·®ååå¾: ãã£ãã·ã¥å©ç¨', filename); 345 return eventData; 346 } catch (e) { 347 // ãã¼ã¹å¤±ææã¯ååå¾ 348 } 349 } 350 } 351 // 夿´ãã or ãã£ãã·ã¥ãªã: ååå¾ 352 const fetchUrl = lastModified ? `${url}?t=${encodeURIComponent(lastModified)}` : `${url}?t=${Date.now()}`; 353 const response = await fetch(fetchUrl, { cache: 'no-cache', headers: { 'Cache-Control': 'no-cache' } }); 354 if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); 355 eventData = await response.json(); 356 if (lastModified) { 357 localStorage.setItem(lmKey, lastModified); 358 localStorage.setItem(dataKey, JSON.stringify(eventData)); 359 } 360 console.log('å·®ååå¾: ååå¾', filename); 361 return eventData; 362 } 363 364 /** 365 * ã¤ãã³ãã®ãã£ãã·ã¥ãç¡å¹åãã¹ããã©ãããå¤å® 366 * @param {string} eventDate - ã¤ãã³ãæ¥ä»ï¼YYYY-MM-DDå½¢å¼ï¼ 367 * @returns {boolean} ãã£ãã·ã¥ãç¡å¹åãã¹ããã©ãã 368 */ 369 shouldDisableCacheForEvent(eventDate) { 370 if (!eventDate) return false; 371 372 try { 373 const eventDateTime = new Date(eventDate); 374 const now = new Date(); 375 const threeMonthsAgo = new Date(); 376 threeMonthsAgo.setMonth(now.getMonth() - 3); 377 378 // 3ã¶æä»¥å ã®ã¤ãã³ãã¯ãã£ãã·ã¥ãç¡å¹å 379 return eventDateTime >= threeMonthsAgo; 380 } catch (error) { 381 console.error('æ¥ä»è§£æã¨ã©ã¼:', error); 382 return false; // ã¨ã©ã¼ã®å ´åã¯ãã£ãã·ã¥ãä½¿ç¨ 383 } 384 } 385 386 /** 387 * ç¹å®ã®ã¤ãã³ããã¼ã¿ãèªã¿è¾¼ãï¼ãªã³ããã³ãã»ãã¤ããªãããã£ãã·ã¥ï¼ 388 * @param {string} eventId - ã¤ãã³ãID 389 * @param {string} filename - ã¤ãã³ããã¡ã¤ã«å 390 * @param {boolean} forceRefresh - å¼·å¶çã«ææ°ãã¼ã¿ãåå¾ãããã©ãã 391 * @param {string} eventDate - ã¤ãã³ãæ¥ä»ï¼YYYY-MM-DDå½¢å¼ï¼ 392 * @returns {Promise<Object>} ã¤ãã³ããã¼ã¿ 393 */ 394 async loadSpecificEventData(eventId, filename, forceRefresh = false, eventDate = null) { 395 try { 396 if (forceRefresh) { 397 // å¼·å¶æ´æ°ã®å ´åã¯å¸¸ã«ææ°ãã¼ã¿ãåå¾ 398 console.log(`å¼·å¶æ´æ°: ${filename}`); 399 const data = await this.fetchEventData(filename, true, eventDate); 400 return data; 401 } 402 403 // ãã¤ããªãããã£ãã·ã¥æ¦ç¥ãä½¿ç¨ 404 const shouldUseCache = !this.shouldDisableCacheForEvent(eventDate); 405 406 if (shouldUseCache) {
407 // å¤ãã¤ãã³ãã¯ãã£ãã·ã¥ããåå¾ã試ã¿ã 408 const cacheKey = `${this.STORAGE_KEYS.EVENT_DATA_PREFIX}${eventId}`; 409 const cachedData = this.getFromCache(cacheKey); 410 411 if (cachedData) { 412 console.log(`ãã£ãã·ã¥ããåå¾: ${filename}`); 413 return cachedData; 414 } 415 416 // ãã£ãã·ã¥ã«ãªããã°æ°è¦åå¾ãã¦ãã£ãã·ã¥ã«ä¿å 417 const data = await this.fetchEventData(filename, false, eventDate); 418 this.saveToCache(cacheKey, data); 419 return data; 420 } else { 421 // ææ°ã¤ãã³ãã¯å¸¸ã«ææ°ãã¼ã¿ãåå¾ 422 console.log(`ææ°ãã¼ã¿åå¾: ${filename}`); 423 const data = await this.fetchEventData(filename, false, eventDate); 424 return data; 425 } 426 } catch (error) { 427 console.error(`ã¤ãã³ããã¼ã¿ ${filename} ã®èªã¿è¾¼ã¿ã«å¤±æãã¾ãã:`, error); 428 throw error; 429 } 430 } 431 432 /** 433 * ãã£ãã·ã¥ãã¯ãªã¢ï¼event-listã¯é¤ãï¼ 434 */ 435 clearCache() { 436 try { 437 // ã¤ãã³ããã¼ã¿ã®ãã£ãã·ã¥ã®ã¿ã¯ãªã¢ï¼event-listã¯ãã£ãã·ã¥ãã¦ããªãã®ã§ã¹ãããï¼ 438 Object.values(this.STORAGE_KEYS).forEach(key => { 439 if (key === this.STORAGE_KEYS.EVENT_LIST) { 440 // event-listã¯ãã£ãã·ã¥ãã¦ããªãã®ã§ã¹ããã 441 return; 442 } 443 444 if (key.includes('_PREFIX')) { 445 // ãã¬ãã£ãã¯ã¹ã®å ´åã¯é¢é£ãããã¹ã¦ã®ãã¼ãåé¤ 446 const prefix = key; 447 for (let i = 0; i < localStorage.length; i++) { 448 const storageKey = localStorage.key(i); 449 if (storageKey && storageKey.startsWith(prefix)) { 450 localStorage.removeItem(storageKey); 451 } 452 } 453 } else { 454 localStorage.removeItem(key); 455 } 456 }); 457 console.log('ã¤ãã³ããã¼ã¿ãã£ãã·ã¥ãã¯ãªã¢ãã¾ããï¼event-listã¯å¯¾è±¡å¤ï¼'); 458 } catch (error) { 459 console.error('ãã£ãã·ã¥ã¯ãªã¢ã¨ã©ã¼:', error); 460 } 461 } 462 463 /** 464 * å ¨ãã¼ã¿ãå¼·å¶æ´æ° 465 * @returns {Promise<Object>} æ´æ°ããããã¼ã¿ 466 */ 467 async forceRefreshAllData() { 468 try { 469 console.log('å ¨ãã¼ã¿ã®å¼·å¶æ´æ°ãéå§ãã¾ã'); 470 471 // ãã£ãã·ã¥ãã¯ãªã¢ 472 this.clearCache(); 473 474 // ãã¼ãã£ã³ã°ç¶æ ããªã»ãã 475 this.loadingState.isLoading = true; 476 this.loadingState.loadingProgress = 0; 477 this.loadingState.isInitialDataLoaded = false; 478 this.loadingState.loadingError = null; 479 480 // ã¤ãã³ããªã¹ããåèªã¿è¾¼ã¿ 481 const eventList = await this.loadEventList(); 482 483 // åªå ã¤ãã³ããã¼ã¿ãå¼·å¶æ´æ°ã§èªã¿è¾¼ã¿ 484 const priorityEventData = await this.loadPriorityEventDataWithRefresh(eventList, 3); 485 486 // æ®ãã®ã¤ãã³ããã¼ã¿ãããã¯ã°ã©ã¦ã³ãã§å¼·å¶æ´æ° 487 setTimeout(async () => { 488 await this.loadRemainingEventDataWithRefresh(eventList, 3); 489 }, 100); 490 491 console.log('å ¨ãã¼ã¿ã®å¼·å¶æ´æ°ãå®äºãã¾ãã'); 492 493 return { 494 eventList, 495 eventData: priorityEventData 496 }; 497 } catch (error) { 498 console.error('å ¨ãã¼ã¿ã®å¼·å¶æ´æ°ã«å¤±æãã¾ãã:', error); 499 this.loadingState.loadingError = 'å ¨ãã¼ã¿ã®æ´æ°ã«å¤±æãã¾ãã'; 500 throw error; 501 } 502 } 503 504 /** 505 * ææ°ã®ã¤ãã³ããã¼ã¿ãå¼·å¶æ´æ°ã§èªã¿è¾¼ã 506 * @param {Array} eventList - ã¤ãã³ããªã¹ã 507 * @param {number} count - èªã¿è¾¼ãã¤ãã³ãæ° 508 * @returns {Promise<Object>} èªã¿è¾¼ãã ã¤ãã³ããã¼ã¿ 509 */ 510 async loadPriorityEventDataWithRefresh(eventList, count = 3) { 511 const priorityEvents = eventList.slice(0, count); 512 const eventData = {}; 513 514 for (let i = 0; i < priorityEvents.length; i++) { 515 const event = priorityEvents[i]; 516 try { 517 // å¼·å¶ååå¾: lastModifiedç¡è¦ 518 const url = `data/${event.file}`; 519 const fetchUrl = `${url}?t=${Date.now()}`; 520 const response = await fetch(fetchUrl, { cache: 'no-cache', headers: { 'Cache-Control': 'no-cache' } }); 521 if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); 522 const data = await response.json(); 523 eventData[event.id] = data; 524 this.saveToCache(`${this.STORAGE_KEYS.EVENT_DATA_PREFIX}${event.id}`, data); 525 this.updateProgress(20 + Math.floor((i + 1) / priorityEvents.length * 30)); 526 } catch (error) { 527 console.error(`ã¤ãã³ããã¼ã¿ ${event.file} ã®å¼·å¶æ´æ°ã«å¤±æãã¾ãã:`, error); 528 } 529 } 530 this.loadingState.isInitialDataLoaded = true; 531 return eventData; 532 } 533 534 /** 535 * æ®ãã®ã¤ãã³ããã¼ã¿ãå¼·å¶æ´æ°ã§ããã¯ã°ã©ã¦ã³ãèªã¿è¾¼ã¿ 536 * @param {Array} eventList - ã¤ãã³ããªã¹ã 537 * @param {number} startIndex - éå§ã¤ã³ããã¯ã¹ 538 * @returns {Promise<Object>} èªã¿è¾¼ãã ã¤ãã³ããã¼ã¿ 539 */ 540 async loadRemainingEventDataWithRefresh(eventList, startIndex = 3) { 541 const remainingEvents = eventList.slice(startIndex); 542 const eventData = {}; 543 for (let i = 0; i < remainingEvents.length; i++) { 544 const event = remainingEvents[i];
545 try { 546 // å¼·å¶ååå¾: lastModifiedç¡è¦ 547 const url = `data/${event.file}`; 548 const fetchUrl = `${url}?t=${Date.now()}`; 549 const response = await fetch(fetchUrl, { cache: 'no-cache', headers: { 'Cache-Control': 'no-cache' } }); 550 if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); 551 const data = await response.json(); 552 eventData[event.id] = data; 553 this.saveToCache(`${this.STORAGE_KEYS.EVENT_DATA_PREFIX}${event.id}`, data); 554 this.updateProgress(50 + Math.floor((i + 1) / remainingEvents.length * 50)); 555 } catch (error) { 556 console.error(`ã¤ãã³ããã¼ã¿ ${event.file} ã®å¼·å¶æ´æ°ã«å¤±æãã¾ãã:`, error); 557 } 558 } 559 this.loadingState.isLoading = false; 560 this.updateProgress(100); 561 return eventData; 562 } 563} 564 565// ã°ãã¼ãã«ã¤ã³ã¹ã¿ã³ã¹ãã¨ã¯ã¹ãã¼ã 566const loadingManager = new LoadingManager();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.