Advertisement
Guest User

Untitled

a guest
Jan 12th, 2018
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 51.38 KB | None | 0 0
  1. var host = "www.warcraftlogs.com"
  2. var scheme = "https"
  3.  
  4. // Initialize fzip
  5. var fzip = {}
  6. fzip.FZip = window.runtime.deng.fzip.FZip
  7. fzip.FZipFile = window.runtime.deng.fzip.FZipFile
  8.  
  9. // Get ByteArrays from Local Store
  10. var baUser = null
  11. var baRemember = false
  12. var baPassword = null
  13. var storedUser = ''
  14. var storedPassword = ''
  15.  
  16. // Assume the local store can get corrupted and be robust
  17. try {
  18. baUser = air.EncryptedLocalStore.getItem('username')
  19. baRemember = air.EncryptedLocalStore.getItem('remember')
  20. baPassword = baRemember ? air.EncryptedLocalStore.getItem('password') : null
  21. storedUser = baUser ? baUser.readUTFBytes(baUser.bytesAvailable) : ''
  22. storedPassword = baPassword ? baPassword.readUTFBytes(baPassword.bytesAvailable) : ''
  23. } catch (e) {
  24. }
  25.  
  26. var baGuild = null
  27. var baRegionID = null
  28. var baTeamID = null
  29. var baVisibility = null
  30. var baChooseFights = null
  31. var baDirectory = null
  32. var baFile = null
  33.  
  34. var storedGuild = ''
  35. var storedRegionID = ''
  36. var storedTeamID = ''
  37. var storedVisibility = ''
  38. var storedChooseFights = ''
  39. var storedIncludeTrash = ''
  40. var storedDirectory = ''
  41.  
  42. var selectedPrivacy = 0
  43.  
  44. var reportUIMode = "upload"
  45.  
  46. try {
  47. baGuild = air.EncryptedLocalStore.getItem('guild')
  48. baRegionID = air.EncryptedLocalStore.getItem('region')
  49. baTeamID = air.EncryptedLocalStore.getItem('team')
  50. baVisibility = air.EncryptedLocalStore.getItem('visibility')
  51. baChooseFights = air.EncryptedLocalStore.getItem('choosefights')
  52. baIncludeTrash = air.EncryptedLocalStore.getItem('includetrash')
  53. baDirectory = air.EncryptedLocalStore.getItem('directory')
  54. baFile = air.EncryptedLocalStore.getItem('file')
  55. } catch (e) {
  56. }
  57.  
  58. var storedDisplayName = ''
  59.  
  60. var loggedIn = false
  61.  
  62. var guildList = 'Lost connection. Quit the app and log in again.'
  63. var selectedGuild
  64. var selectedRegion = 0
  65. var selectedTeam = 0
  66.  
  67. var liveLogging = false
  68. var loader = null
  69. var liveLogChangeInterval = 5000
  70. var liveLogPosition = 0
  71. var liveLogLastModified = 0
  72. var terminateLogging = false
  73. var reportCode = ''
  74. var lastReportCode = ''
  75. var logFights = new Array()
  76.  
  77. var unchangedCount = 0
  78.  
  79. var debugMode = false
  80.  
  81. var splitFileTimestamp = 0
  82. var splitFileStream
  83. var splittingLogFile = false
  84. var previousTimestampForSplit = 0
  85.  
  86. var scanningLogFileForRaids = false
  87. var scannedRaids = new Array()
  88. var raidsToUpload = new Array()
  89.  
  90. var liveLoggingAutoStartDesc = ''
  91.  
  92. function onInvoke(evt)
  93. {
  94. if (!evt.arguments.length)
  95. return
  96.  
  97. for (var i = 0; i < evt.arguments.length; ++i) {
  98. if (evt.arguments[i] == 'debug')
  99. debugMode = true
  100. if (evt.arguments[i].indexOf('livelog=') != -1) {
  101. var desc = evt.arguments[i].substr(8, evt.arguments[i].length)
  102. if (desc.length <= 0)
  103. continue
  104. liveLoggingAutoStartDesc = desc
  105. }
  106. }
  107. }
  108.  
  109. air.NativeApplication.nativeApplication.addEventListener(air.InvokeEvent.INVOKE, onInvoke);
  110.  
  111. function logToDebugPanel(str)
  112. {
  113. var panel = document.getElementById('inner-debug-panel')
  114. var line = document.createElement('div')
  115. line.innerHTML = str
  116. panel.appendChild(line);
  117. panel.scrollTop = panel.scrollHeight
  118. }
  119.  
  120. function resetLoginButton()
  121. {
  122. document.getElementById('login-button').innerHTML = 'Log In'
  123. }
  124.  
  125. function resetUploadButton()
  126. {
  127. document.getElementById('upload-button').innerHTML = 'Go!'
  128. document.getElementById('fights-button').innerHTML = 'Go!'
  129. }
  130.  
  131. function logout()
  132. {
  133. resetLoginButton()
  134. document.getElementById('logout-link').style.display = 'none'
  135. document.getElementById('logincontent').style.display = 'block'
  136. document.getElementById('reportcontent').style.display = 'none'
  137. document.getElementById('email').focus()
  138. document.getElementById('email').select()
  139. }
  140.  
  141. function selectPrivacy(setting)
  142. {
  143. document.getElementById('privacy-0').removeAttribute('selected')
  144. document.getElementById('privacy-1').removeAttribute('selected')
  145. document.getElementById('privacy-2').removeAttribute('selected')
  146.  
  147. document.getElementById('privacy-' + setting).setAttribute('selected', 'true')
  148. selectedPrivacy = setting
  149. }
  150.  
  151. function displayReportUI()
  152. {
  153. storedGuild = baGuild ? baGuild.readUTFBytes(baGuild.bytesAvailable) : ''
  154. storedRegionID = baRegionID ? baRegionID.readUTFBytes(baRegionID.bytesAvailable) : ''
  155. storedTeamID = baTeamID ? baTeamID.readUTFBytes(baTeamID.bytesAvailable) : ''
  156.  
  157. storedVisibility = baVisibility ? baVisibility.readUTFBytes(baVisibility.bytesAvailable) : ''
  158. storedChooseFights = baChooseFights ? baChooseFights.readUTFBytes(baChooseFights.bytesAvailable) : ''
  159. storedIncludeTrash = baIncludeTrash ? baIncludeTrash.readUTFBytes(baIncludeTrash.bytesAvailable) : ''
  160.  
  161. storedDirectory = baDirectory ? baDirectory.readUTFBytes(baDirectory.bytesAvailable) : ''
  162. storedFile = baFile ? baFile.readUTFBytes(baFile.bytesAvailable) : ''
  163.  
  164. selectReportPage('first')
  165.  
  166. document.getElementById('logout-link').style.display = 'inline'
  167. document.getElementById('logincontent').style.display = 'none'
  168. document.getElementById('reportcontent').style.display = 'block'
  169.  
  170. buildGuilds()
  171.  
  172. if (storedVisibility !== '')
  173. selectPrivacy(parseInt(storedVisibility))
  174. else
  175. selectPrivacy(0)
  176.  
  177. if (storedChooseFights !== '')
  178. document.getElementById('fight-chooser').checked = (storedChooseFights == '1')
  179.  
  180. if (storedIncludeTrash !== '')
  181. document.getElementById('include-trash').checked = (storedIncludeTrash == '1')
  182.  
  183. if (storedDirectory !== '') {
  184. document.getElementById('directory').innerText = storedDirectory
  185. setFileDisplay(storedDirectory, 'directory-display')
  186. }
  187.  
  188. if (storedFile !== '') {
  189. document.getElementById('logfile').innerText = storedFile
  190. setFileDisplay(storedFile, 'logfile-display')
  191. }
  192.  
  193. if (storedRegionID !== '')
  194. selectRegion(parseInt(storedRegionID))
  195.  
  196. if (liveLoggingAutoStartDesc != '') {
  197. setReportUIMode('livelog')
  198. selectReportPage('upload')
  199. document.getElementById('description').value = liveLoggingAutoStartDesc
  200. startLiveLoggingSession(liveLoggingAutoStartDesc, document.getElementById('directory').innerText)
  201. liveLoggingAutoStartDesc = ''
  202. }
  203. }
  204.  
  205. var appUpdater
  206.  
  207. function onUpdateError(event) {
  208. alert("Failed to parse the update descriptor file: " + event.toString())
  209. }
  210.  
  211. function onClientUpdate(event) {
  212. //starts the update process
  213. appUpdater.checkNow();
  214. }
  215.  
  216. function checkForUpdate()
  217. {
  218. appUpdater = new runtime.air.update.ApplicationUpdaterUI()
  219.  
  220. appUpdater.updateURL = scheme + "://" + host + "/client/update.xml"
  221.  
  222. //we set the event handlers for INITIALIZED nad ERROR
  223. appUpdater.addEventListener(runtime.air.update.events.UpdateEvent.INITIALIZED, onClientUpdate)
  224. appUpdater.addEventListener(runtime.air.update.events.StatusUpdateErrorEvent.UPDATE_ERROR, onUpdateError)
  225.  
  226. //we can hide the dialog asking for permission for checking for a new update;
  227. //if you want to see it just leave the default value (or set true).
  228. appUpdater.isCheckForUpdateVisible = false
  229.  
  230. //if isFileUpdateVisible is set to true, File Update, File No Update,
  231. //and File Error dialog boxes will be displayed
  232. appUpdater.isFileUpdateVisible = false
  233.  
  234. //if isInstallUpdateVisible is set to true, the dialog box for installing the update is visible
  235. appUpdater.isInstallUpdateVisible = false
  236.  
  237. //we initialize the updater
  238. appUpdater.initialize()
  239. }
  240.  
  241. function fillInLoginForm()
  242. {
  243. setTimeout(checkForUpdate, 200)
  244.  
  245. document.getElementById('email').value = storedUser
  246. document.getElementById('password').value = storedPassword
  247. document.getElementById('remember').checked = baRemember ? true : false
  248.  
  249. if (baRemember)
  250. login(document.getElementById('email').value, document.getElementById('password').value, document.getElementById('remember').checked)
  251.  
  252. document.getElementById('email').focus()
  253. document.getElementById('email').select()
  254. }
  255.  
  256. function setStatusText(text, hideSpinny)
  257. {
  258. }
  259.  
  260. function setProgressStatusText(text, id)
  261. {
  262. document.getElementById(id).innerHTML = text
  263. }
  264.  
  265. function setErrorText(text)
  266. {
  267. var errorBlock = document.getElementById('errorblock')
  268. if (text == '')
  269. errorBlock.style.display = 'none'
  270. else
  271. errorBlock.style.display = 'block'
  272.  
  273. document.getElementById('errortext').innerHTML = text
  274. document.body.offsetWidth
  275. }
  276.  
  277. function setWarningText(text)
  278. {
  279. var errorBlock = document.getElementById('warningblock')
  280. if (text == '')
  281. errorBlock.style.display = 'none'
  282. else
  283. errorBlock.style.display = 'block'
  284.  
  285. document.getElementById('warningtext').innerHTML = text
  286. document.body.offsetWidth
  287. }
  288.  
  289. function setCancelButtonVisible(visible)
  290. {
  291. var cancelButton = document.getElementById('cancelbutton')
  292. if (!visible)
  293. cancelButton.style.display = 'none'
  294. else
  295. cancelButton.style.display = 'inline-block'
  296. }
  297.  
  298. function login(user, password, remember)
  299. {
  300. setErrorText('');
  301.  
  302. if (user == '' || password == '') {
  303. setErrorText("You must specify both a username and a password.")
  304. return
  305. }
  306.  
  307. document.getElementById('login-button').innerHTML = '<img id="button-spinny" src="img/spinny.gif">'
  308.  
  309. var loginFormData = new FormData();
  310.  
  311. loginFormData.append("version", "4.37")
  312. loginFormData.append("email", user)
  313. loginFormData.append("password", password)
  314.  
  315. var request = new XMLHttpRequest()
  316. request.onload = function(evt) {
  317. if (request.status != 200) {
  318. setErrorText('Error occurred trying to log in!')
  319. return;
  320. }
  321.  
  322. if (request.responseText.length > 10 && request.responseText.substring(0, 10) == "<div id=\"g") {
  323. loggedIn = true;
  324.  
  325. try {
  326. baUser = new air.ByteArray
  327. baUser.writeUTFBytes(user)
  328. air.EncryptedLocalStore.setItem('username', baUser)
  329. storedUser = user
  330.  
  331. if (remember) {
  332. baRemember = new air.ByteArray
  333. baRemember.writeUTFBytes("true")
  334. air.EncryptedLocalStore.setItem('remember', baRemember)
  335. baPassword = new air.ByteArray
  336. baPassword.writeUTFBytes(password)
  337. air.EncryptedLocalStore.setItem('password', baPassword)
  338. storedPassword = password
  339. } else {
  340. air.EncryptedLocalStore.removeItem('remember')
  341. baRemember = null
  342. air.EncryptedLocalStore.removeItem('password')
  343. baPassword = null
  344. storedPassword = ''
  345. }
  346. } catch (e) {
  347. }
  348.  
  349. guildList = request.responseText
  350. displayReportUI()
  351. } else {
  352. var errorText = request.responseText
  353. if (!errorText)
  354. errorText = "The server sent an empty response. Login must have failed somehow.";
  355. setErrorText(errorText)
  356. }
  357. document.getElementById('login-button').innerHTML = 'Log In'
  358. };
  359. request.open("POST", scheme + "://" + host + "/accounts/desktoploginwarcraft/")
  360. request.send(loginFormData)
  361. }
  362.  
  363. var logText = ''
  364. var file
  365. var logStream
  366. var outputFile
  367.  
  368. function LargeAsyncFileReader()
  369. {
  370. var _bufferSize = 8388608
  371. var _buffer
  372. var _fileStream
  373. var _file
  374. var _complete
  375.  
  376. this.isComplete = function isComplete() { return _complete; }
  377.  
  378. this.onComplete = function onComplete(evt) { _complete = true; }
  379.  
  380. this.openAsync = function openAsync(file, fileMode) {
  381. _complete = false
  382.  
  383. _buffer = new air.ByteArray
  384. _fileStream = new air.FileStream
  385. _fileStream.readAhead = _bufferSize
  386. _fileStream.addEventListener(air.Event.COMPLETE, this.onComplete)
  387. _fileStream.openAsync(file, fileMode)
  388. _file = file
  389. }
  390.  
  391. this.bytesAvailable = function bytesAvailable() { return _fileStream.bytesAvailable }
  392.  
  393. this.position = function position() { return _fileStream.position }
  394.  
  395. this.seek = function seek(pos) {
  396. _fileStream.position = pos
  397. }
  398.  
  399. this.file = function file() { return _file }
  400.  
  401. this.readUTFChunk = function readUTFChunk() {
  402. var bytesToRead = Math.min(_bufferSize, _fileStream.bytesAvailable)
  403. if (debugMode)
  404. logToDebugPanel("About to do a readBytes with the number of bytes being: " + bytesToRead + ".")
  405. if (!bytesToRead)
  406. return ''
  407. var startPosition = _fileStream.position
  408. _fileStream.readBytes(_buffer, 0, bytesToRead)
  409. if (_complete) {
  410. // We're at the end of the file. Just return it all.
  411. if (debugMode)
  412. logToDebugPanel("No bytes available following read. Return everything.")
  413. var resultString = _buffer.readUTFBytes(_buffer.length)
  414. _buffer.clear()
  415. return resultString
  416. }
  417. var singleCharacterString = ''
  418. var i = bytesToRead - 1
  419. var maxLineSize = 256000;
  420. for (; i >= 0; --i) {
  421. maxLineSize--
  422. if (maxLineSize == 0)
  423. throw "This file is corrupt and contains over 256k of text with no newlines.";
  424. _buffer.position = i
  425. singleCharacterString = _buffer.readUTFBytes(1)
  426. if (singleCharacterString == "\n")
  427. break
  428. }
  429. _buffer.position = 0
  430. var resultString = ''
  431. if (i > 0) {
  432. _buffer.position = 0
  433. resultString = _buffer.readUTFBytes(i)
  434. }
  435. _fileStream.position = startPosition + i + 1
  436. if (debugMode)
  437. logToDebugPanel("Adjusting position to: " + _fileStream.position + ".")
  438. _buffer.clear()
  439. return resultString
  440. }
  441.  
  442. this.close = function close() {
  443. _fileStream.close()
  444. _fileStream = null
  445. _file = null
  446. _buffer = null
  447. _chunkHandler = null
  448. _complete = false
  449. }
  450. }
  451.  
  452. function updateProgress(percent, bar)
  453. {
  454. var barInterior = document.getElementById(bar).firstChild;
  455. barInterior.style.width = percent + '%';
  456.  
  457. var barNumber = document.getElementById(bar + "-number")
  458. barNumber.innerHTML = "(" + percent + "%)"
  459. }
  460.  
  461. var isLogValid = false
  462. var parsedLineCount = 0
  463.  
  464. var actorsString = ''
  465. var abilitiesString = ''
  466. var tuplesString = ''
  467. var petsString = ''
  468. var eventsString = ''
  469.  
  470. var currentLinePosition = 0
  471. var lines = null
  472. var lineThreshold = 5000
  473. var oldFilePosition = 0
  474.  
  475. var currentTimeout
  476.  
  477. var tempFile = null
  478. var zipArchive = null
  479.  
  480. var logVersion = 1
  481. var mythic = 0
  482.  
  483. function finishChunk()
  484. {
  485. currentLinePosition = 0
  486. lines = null
  487. lineCount = 0
  488.  
  489. deleteTempFile()
  490.  
  491. if (liveLogging)
  492. parsedLineCount = 0
  493.  
  494. logFights = new Array()
  495. }
  496.  
  497. function goHome()
  498. {
  499. setErrorText('')
  500. cancelOrFinish('first')
  501. }
  502.  
  503. function goToPatreon()
  504. {
  505. var url = "https://www.patreon.com/warcraftlogs";
  506. var urlReq = new air.URLRequest(url);
  507. air.navigateToURL(urlReq);
  508. }
  509.  
  510. function cancelOrFinish(reportPage)
  511. {
  512. finishChunk()
  513.  
  514. if (currentTimeout)
  515. clearTimeout(currentTimeout)
  516.  
  517. resetUploadButton()
  518.  
  519. selectReportPage(reportPage)
  520.  
  521. isLogValid = false
  522. setStatusText('')
  523. setCancelButtonVisible(false)
  524. clearParserState()
  525. liveLogging = false
  526. liveLogPosition = 0
  527. liveLogLastModified = 0
  528. logFights = new Array()
  529. lastCombatEventTime = 0
  530. terminateLogging = false
  531. unchangedCount = 0
  532. reportCode = ''
  533. file = null
  534.  
  535. splittingLogFile = false
  536. splitFileTimestamp = 0
  537. previousTimestampForSplit = 0
  538.  
  539. scanningLogFileForRaids = false
  540. scannedRaids = new Array()
  541. raidsToUpload = new Array()
  542.  
  543. if (logStream) {
  544. logStream.close()
  545. logStream = null
  546. }
  547.  
  548. if (splitFileStream) {
  549. splitFileStream.close()
  550. splitFileStream = null
  551. }
  552. }
  553.  
  554. function doProgress(e)
  555. {
  556. var loaded = e.bytesLoaded;
  557. var total = e.bytesTotal;
  558. var percentLoaded = Math.ceil(( loaded / total ) * 100)
  559. updateProgress(percentLoaded, "upload-progress")
  560. }
  561.  
  562. function doCreateReportComplete(e) {
  563. if (loader.data.substring(0, 7) == "Success") {
  564. selectReportPage('progress')
  565. lastReportCode = reportCode = loader.data.substring(8)
  566. if (liveLogging) {
  567. setProgressStatusText("Report created. Live logging has started.", 'livelog-progress-status')
  568. currentTimeout = setTimeout(checkForLiveLogChanges, liveLogChangeInterval)
  569. } else {
  570. currentTimeout = setTimeout(openLogFile, 0);
  571. }
  572. } else {
  573. cancelOrFinish('upload')
  574. setErrorText(loader.data)
  575. }
  576.  
  577. loader = null
  578. }
  579.  
  580. function deleteTempFile()
  581. {
  582. if (tempFile) {
  583. tempFile.cancel() // Stop the upload.
  584. tempFile.deleteFile()
  585. tempFile = null
  586. }
  587. }
  588.  
  589. function doMasterTableComplete(e) {
  590. if (e.data.substring(0, 7) == "Success") {
  591. updateProgress(100, "upload-progress")
  592. setStatusText("Upload of New Players, NPCs and Pets Successful.");
  593. currentTimeout = setTimeout(compressReportSegment, 200);
  594. deleteTempFile()
  595. } else {
  596. cancelOrFinish('upload')
  597. setErrorText(e.data)
  598. }
  599. }
  600.  
  601. function doError(e) {
  602. // Uh-oh!
  603. cancelOrFinish('upload')
  604. setErrorText("Failed to upload.")
  605. deleteTempFile()
  606. }
  607.  
  608. function doChunkComplete(e) {
  609. if (e.data == "Success") {
  610. updateProgress(100, "upload-progress")
  611. setUploadProgressContainer(false)
  612. if (liveLogging) {
  613. setProgressStatusText("Data successfully uploaded. Waiting for more data.", "livelog-progress-status")
  614. } else
  615. setProgressStatusText("Reading Combat Log", "logfile-progress-status")
  616. finishChunk()
  617. if (terminateLogging) {
  618. handleLogTermination()
  619. } else if (!liveLogging || logStream)
  620. currentTimeout = setTimeout(readFileChunk, 200)
  621. else
  622. currentTimeout = setTimeout(checkForLiveLogChanges, liveLogChangeInterval)
  623. } else {
  624. cancelOrFinish('upload')
  625. setErrorText(e.data)
  626. }
  627. }
  628.  
  629. function uploadReportSegment()
  630. {
  631. currentTimeout = 0
  632.  
  633. tempFile.addEventListener(air.DataEvent.UPLOAD_COMPLETE_DATA, doChunkComplete)
  634. tempFile.addEventListener(air.ProgressEvent.PROGRESS, doProgress)
  635. tempFile.addEventListener(air.SecurityErrorEvent.SECURITY_ERROR, doError)
  636. tempFile.addEventListener(air.IOErrorEvent.IO_ERROR, doError)
  637.  
  638. var request = new air.URLRequest(scheme + "://" + host + "/reports/addtolog/")
  639.  
  640. // SETTINGS FOR THE REQUEST
  641. request.cacheResponse = false
  642. request.method = air.URLRequestMethod.POST
  643.  
  644. // SOME VARIABLES (E.G. A FOLDER NAME TO SAVE THE FILE)
  645. var vars = new air.URLVariables()
  646. vars.report = reportCode
  647. vars.start = startTime
  648. vars.end = endTime
  649. vars.mythic = mythic
  650. vars.livelog = liveLogging ? 1 : 0
  651.  
  652. request.data = vars
  653.  
  654. // UPLOAD THE FILE, DON'T TEST THE SERVER BEFOREHAND
  655. tempFile.upload(request, 'logfile', false)
  656. }
  657.  
  658. function setUploadProgressContainer(visible)
  659. {
  660. var container = document.getElementById('upload-progress-container')
  661. if (visible)
  662. container.style.visibility = ''
  663. else
  664. container.style.visibility = 'hidden'
  665. }
  666.  
  667. function uploadMasterReportTable()
  668. {
  669. currentTimeout = 0
  670.  
  671. tempFile.addEventListener(air.DataEvent.UPLOAD_COMPLETE_DATA, doMasterTableComplete)
  672. tempFile.addEventListener(air.ProgressEvent.PROGRESS, doProgress)
  673. tempFile.addEventListener(air.SecurityErrorEvent.SECURITY_ERROR, doError)
  674. tempFile.addEventListener(air.IOErrorEvent.IO_ERROR, doError)
  675.  
  676. var request = new air.URLRequest(scheme + "://" + host + "/reports/setmastertable/")
  677.  
  678. // SETTINGS FOR THE REQUEST
  679. request.cacheResponse = false
  680. request.method = air.URLRequestMethod.POST
  681.  
  682. // SOME VARIABLES (E.G. A FOLDER NAME TO SAVE THE FILE)
  683. var vars = new air.URLVariables()
  684. vars.report = reportCode
  685.  
  686. request.data = vars
  687.  
  688. // UPLOAD THE FILE, DON'T TEST THE SERVER BEFOREHAND
  689. tempFile.upload(request, 'logfile', false)
  690. }
  691.  
  692. function compressReportSegment()
  693. {
  694. currentTimeout = 0
  695. if (!logFights.length)
  696. return
  697.  
  698. // First, we upload the master file that contains all actors, abilities and tuples.
  699. var fileString = ''
  700. fileString += logVersion + "\n"; // Version. Revs any time we change the file format.
  701.  
  702. // Stitch the events back together into one chunk.
  703. var eventCount = 0
  704. var eventCombinedString = ''
  705. for (var i = 0; i < logFights.length; ++i) {
  706. var fight = logFights[i]
  707. eventCount += fight.eventCount
  708. eventCombinedString += fight.eventsString
  709. }
  710.  
  711. fileString += eventCount + "\n"
  712. fileString += eventCombinedString
  713.  
  714. // The next step is zipping up the events file.
  715. zipArchive = new fzip.FZip
  716. zipArchive.addFileFromString("log.txt", fileString)
  717.  
  718. var outputFileStream = null
  719. try {
  720. tempFile = air.File.createTempFile()
  721. outputFileStream = new air.FileStream()
  722. outputFileStream.open(tempFile, air.FileMode.WRITE)
  723. //outputFileStream.writeUTFBytes(fileString)
  724. zipArchive.serialize(outputFileStream)
  725. outputFileStream.close()
  726. } catch (e) {
  727. if (outputFileStream)
  728. outputFileStream.close()
  729. setErrorText(e)
  730. return
  731. }
  732. zipArchive = null
  733.  
  734. setProgressStatusText("Uploading New Fights", "upload-progress-status")
  735. updateProgress(0, "upload-progress")
  736. currentTimeout = setTimeout(uploadReportSegment, 0)
  737. }
  738.  
  739. function compressReport()
  740. {
  741. currentTimeout = 0
  742. if (!logFights.length)
  743. return
  744.  
  745. // First, we upload the master file that contains all actors, abilities and tuples.
  746. var fileString = ''
  747. fileString += logVersion + "\n"; // Version. Revs any time we change the file format.
  748.  
  749. fileString += lastAssignedActorID + "\n"
  750. buildActorsString()
  751. fileString += actorsString
  752.  
  753. fileString += lastAssignedAbilityID + "\n"
  754. fileString += abilitiesString
  755.  
  756. fileString += lastAssignedTupleID + "\n"
  757. fileString += tuplesString
  758.  
  759. fileString += lastAssignedPetID + "\n"
  760. buildPetsString()
  761. fileString += petsString
  762.  
  763. // The next step is zipping up the tuples file.
  764. zipArchive = new fzip.FZip
  765. zipArchive.addFileFromString("log.txt", fileString)
  766.  
  767. var outputFileStream = null
  768. try {
  769. tempFile = air.File.createTempFile()
  770. outputFileStream = new air.FileStream()
  771. outputFileStream.open(tempFile, air.FileMode.WRITE)
  772. //outputFileStream.writeUTFBytes(fileString)
  773. zipArchive.serialize(outputFileStream)
  774. outputFileStream.close()
  775. } catch (e) {
  776. if (outputFileStream)
  777. outputFileStream.close()
  778. setErrorText(e)
  779. return
  780. }
  781. zipArchive = null
  782.  
  783. setProgressStatusText("Uploading New Players, NPCs and Pets", "upload-progress-status")
  784.  
  785. setUploadProgressContainer(true)
  786.  
  787. updateProgress(0, "upload-progress")
  788. currentTimeout = setTimeout(uploadMasterReportTable, 0)
  789. }
  790.  
  791. function readFileChunk()
  792. {
  793. currentTimeout = 0
  794. var firstLineWasInvalid = false
  795.  
  796. try {
  797. if (debugMode)
  798. logToDebugPanel("Entering readFileChunk with logStream position: " + logStream.position() + ".")
  799. if (!lines) {
  800. oldFilePosition = logStream.position()
  801. lines = logStream.readUTFChunk().split(/\r\n|\n|\r/)
  802. }
  803. var lineCount = 0
  804. for (var i = currentLinePosition; i < lines.length; ++i) {
  805. parsedLineCount++
  806. lineCount++
  807. var validLine = false
  808. if (splittingLogFile) {
  809. var timestamp = scanLogLine(lines[i]);
  810. if (timestamp != -1) {
  811. validLine = true
  812. if (splitFileTimestamp == 0 || timestamp > previousTimestampForSplit + 60 * 1000 * 60 * 4) {
  813. splitFileTimestamp = timestamp
  814. createNewSplitFile()
  815. }
  816. var lineString = lines[i] + "\n";
  817. splitFileStream.writeUTFBytes(lineString)
  818. previousTimestampForSplit = timestamp
  819. }
  820. } else {
  821. validLine = parseLogLine(lines[i], scanningLogFileForRaids);
  822. if (!validLine) {
  823. var trimmedLine = lines[i].trim()
  824. if (!trimmedLine.length)
  825. validLine = true
  826. }
  827. }
  828. if (!validLine && !isLogValid) {
  829. setErrorText('Line 1 - This is not a valid log file. Bad line was: ' + lines[i])
  830. firstLineWasInvalid = true
  831. break
  832. }
  833. isLogValid = true
  834. lineCount++
  835. if (lineCount >= lineThreshold) {
  836. if (debugMode)
  837. logToDebugPanel("Line threshold of " + lineThreshold + " exceeded. Calling readFileChunk again.")
  838. currentLinePosition = i + 1
  839. currentTimeout = setTimeout(readFileChunk, 0)
  840. updateProgress(Math.ceil(100 * (oldFilePosition + (currentLinePosition / lines.length) * (logStream.position() - oldFilePosition) - liveLogPosition) / (logStream.file().size - liveLogPosition)), "logfile-progress")
  841. return
  842. }
  843. }
  844.  
  845. if (!firstLineWasInvalid && (logStream.bytesAvailable() || !logStream.isComplete())) {
  846. if (debugMode)
  847. logToDebugPanel("More bytes are available. Our current position is " + logStream.position() + " and bytes available is " + logStream.bytesAvailable() + ".")
  848. lines = null
  849. currentLinePosition = 0
  850. updateProgress(Math.ceil(100 * (logStream.position() - liveLogPosition) / (logStream.file().size - liveLogPosition)), "logfile-progress")
  851. if (!logFights.length)
  852. currentTimeout = setTimeout(readFileChunk, 0)
  853. else {
  854. setProgressStatusText("Processed " + logFights.length + " New Fights. Compressing Combat Log Data", "livelog-progress-status")
  855. currentTimeout = setTimeout(compressReport, 200)
  856. }
  857. return
  858. }
  859. }
  860. catch (e) {
  861. setErrorText("Line " + parsedLineCount + " - " + e)
  862. isLogValid = false
  863. logToDebugPanel(e)
  864. }
  865.  
  866. var position = logStream ? logStream.position() : 0
  867. if (debugMode)
  868. logToDebugPanel("Finished readFileChunk with position of " + position + ".")
  869. currentLinePosition = 0
  870. lines = null
  871. if (logStream) {
  872. logStream.close()
  873. logStream = null
  874. }
  875. lineCount = 0
  876. parsedLineCount = 0
  877.  
  878. if (isLogValid) {
  879. if (liveLogging) {
  880. liveLogPosition = position
  881. if (debugMode)
  882. logToDebugPanel("Set live log position to " + liveLogPosition + ".")
  883. if (!logFights.length) {
  884. currentTimeout = setTimeout(checkForLiveLogChanges, liveLogChangeInterval)
  885. setProgressStatusText("Data processed. Waiting for end of fight to be logged before uploading.", "livelog-progress-status")
  886. return
  887. }
  888. setProgressStatusText("Processed " + logFights.length + " New Fights. Compressing Combat Log Data", "livelog-progress-status")
  889. } else {
  890. pushLogFight(scanningLogFileForRaids)
  891. terminateLogging = true
  892. setProgressStatusText("Compressing Combat Log Data", "livelog-progress-status")
  893. }
  894. if (logFights.length)
  895. currentTimeout = setTimeout(compressReport, 200)
  896. else if (scanningLogFileForRaids)
  897. showFightSelectionUI()
  898. else
  899. handleLogTermination()
  900. } else {
  901. setCancelButtonVisible(false)
  902. clearParserState()
  903. document.getElementById("deletion-archival-ui").style.display = 'none'
  904. if (splittingLogFile) {
  905. fileForDeletionAndArchival = file
  906. document.getElementById("deletelogbutton").innerHTML = "Delete " + file.name
  907. document.getElementById("archivelogbutton").innerHTML = "Archive " + file.name
  908. document.getElementById("deletion-archival-ui").style.display = ''
  909. }
  910. file = null
  911. }
  912. }
  913.  
  914. function openLogFile()
  915. {
  916. currentTimeout = 0
  917.  
  918. var initialText = "Reading Combat Log"
  919. if (splittingLogFile)
  920. initialText = "Splitting Combat Log"
  921. else if (scanningLogFileForRaids)
  922. initialText = "Scanning Combat Log For Raids"
  923.  
  924. setProgressStatusText(initialText, "logfile-progress-status")
  925. updateProgress(0, "logfile-progress")
  926. setCancelButtonVisible(true)
  927.  
  928. logStream = new LargeAsyncFileReader()
  929. logStream.openAsync(file, air.FileMode.READ)
  930. currentTimeout = setTimeout(readFileChunk, 200)
  931. }
  932.  
  933. function processLogFile(description, filename)
  934. {
  935. if (file)
  936. return
  937.  
  938. fileForDeletionAndArchival = null
  939.  
  940. setErrorText('')
  941. setWarningText('')
  942.  
  943. if (!filename) {
  944. setErrorText("You must specify a file.")
  945. return;
  946. }
  947.  
  948. file = new air.File(filename);
  949. if (!file || !file.exists) {
  950. setErrorText("Invalid file chosen.")
  951. file = null
  952. return;
  953. }
  954.  
  955. if (file.size >= 1500000000) {
  956. setErrorText("This file is more than 1.5 gigabytes. Split the log file and upload the pieces separately.")
  957. file = null
  958. return
  959. }
  960.  
  961. if (!raidsToUpload.length && (file.modificationDate.getTime() - file.creationDate.getTime()) > 24 * 60 * 60 * 1000) {
  962. setErrorText("This log file contains more than one day of data. You must either split it before uploading or select specific fights to upload.")
  963. file = null
  964. return
  965. }
  966.  
  967. if (selectedGuild == 0 && selectedRegion <= 0) {
  968. setErrorText("For personal logs, you must specify the region you are uploading to. Hit the <i>Choose...</i> button above and pick a region.");
  969. file = null
  970. return
  971. }
  972.  
  973. try {
  974. baVisibility = new air.ByteArray
  975. baVisibility.writeUTFBytes(selectedPrivacy.toString())
  976. air.EncryptedLocalStore.setItem('visibility', baVisibility)
  977.  
  978. baChooseFights = new air.ByteArray
  979. baChooseFights.writeUTFBytes(document.getElementById('fight-chooser').checked ? '1' : '0')
  980.  
  981. baIncludeTrash = new air.ByteArray
  982. baIncludeTrash.writeUTFBytes(document.getElementById('include-trash').checked ? '1' : '0')
  983.  
  984. air.EncryptedLocalStore.setItem('choosefights', baChooseFights)
  985. } catch (e) {
  986. }
  987.  
  988. var loadingStr = '<img id="button-spinny" src="img/spinny.gif">'
  989. document.getElementById('upload-button').innerHTML = loadingStr
  990. document.getElementById('fights-button').innerHTML = loadingStr
  991.  
  992. updateProgress(0, "logfile-progress")
  993. liveLogging = false
  994.  
  995. currentTimeout = setTimeout(createReport, 0)
  996. }
  997.  
  998. function doTerminateComplete(e) {
  999. if (e.target.data.substring(0, 7) == "Success") {
  1000. updateProgress(100, "upload-progress")
  1001. setStatusText("Cleanup Successful.");
  1002. handleLogDeletionAndArchival()
  1003. } else {
  1004. cancelOrFinish('upload')
  1005. setErrorText(e.target.data)
  1006. }
  1007. }
  1008.  
  1009. function terminateReport()
  1010. {
  1011. currentTimeout = 0
  1012.  
  1013. var request = new air.URLRequest(scheme + "://" + host + "/reports/terminatelog/" + reportCode)
  1014. var loader = new air.URLLoader();
  1015. loader.addEventListener(air.Event.COMPLETE, doTerminateComplete)
  1016. loader.load(request);
  1017. }
  1018.  
  1019. function handleLogTermination() {
  1020. if (liveLogging || splittingLogFile) {
  1021. handleLogDeletionAndArchival()
  1022. return
  1023. }
  1024.  
  1025. setProgressStatusText("Cleaning Up...", "upload-progress-status")
  1026. updateProgress(0, "upload-progress")
  1027. currentTimeout = setTimeout(terminateReport, 0)
  1028. }
  1029.  
  1030. function stopLiveLoggingSession()
  1031. {
  1032. pushLogFight(false)
  1033. if (logFights.length) {
  1034. terminateLogging = true
  1035. setProgressStatusText("Uploading remaining data before ending session...", "livelog-progress-status")
  1036. if (currentTimeout)
  1037. clearTimeout(currentTimeout)
  1038. currentTimeout = setTimeout(compressReport, 200)
  1039. return
  1040. }
  1041. handleLogTermination()
  1042. }
  1043.  
  1044. function handleLogDeletionAndArchival() {
  1045. fileForDeletionAndArchival = file
  1046. var wasLiveLogging = liveLogging
  1047. var wasSplitting = splittingLogFile
  1048. cancelOrFinish('deletion-archival')
  1049.  
  1050. document.getElementById("deletion-archival-ui").style.display = 'none'
  1051.  
  1052. if (fileForDeletionAndArchival) {
  1053. if (wasLiveLogging) {
  1054. var logFile = fileForDeletionAndArchival.resolvePath("WoWCombatLog.txt")
  1055. if (!logFile || !logFile.exists) {
  1056. return
  1057. }
  1058. fileForDeletionAndArchival = logFile
  1059. }
  1060.  
  1061. document.getElementById("deletion-archival-ui").style.display = ''
  1062. document.getElementById("deletelogbutton").innerHTML = "Delete " + fileForDeletionAndArchival.name
  1063. document.getElementById("archivelogbutton").innerHTML = "Archive " + fileForDeletionAndArchival.name
  1064. }
  1065. }
  1066.  
  1067. function viewLog()
  1068. {
  1069. var url = scheme + "://" + host + "/reports/" + lastReportCode + "/";
  1070. var urlReq = new air.URLRequest(url);
  1071. air.navigateToURL(urlReq);
  1072. }
  1073.  
  1074. function createReport()
  1075. {
  1076. var request = new air.URLRequest(scheme + "://" + host + "/reports/create")
  1077.  
  1078. // SETTINGS FOR THE REQUEST
  1079. request.cacheResponse = false
  1080. request.method = air.URLRequestMethod.POST
  1081.  
  1082. // SOME VARIABLES (E.G. A FOLDER NAME TO SAVE THE FILE)
  1083. var vars = new air.URLVariables()
  1084. vars.description = document.getElementById('description').value
  1085.  
  1086. vars.guild = selectedGuild
  1087. vars.team = selectedTeam
  1088. vars.personal = -10000 - selectedRegion // This is dumb, but it lets us share the field for backwards compatibility (and with WildStar)
  1089. vars.visibility = selectedPrivacy
  1090. vars.start = new Date().getTime()
  1091. vars.end = vars.start
  1092.  
  1093. request.data = vars
  1094.  
  1095. loader = new air.URLLoader()
  1096. loader.addEventListener(air.Event.COMPLETE, doCreateReportComplete)
  1097. loader.addEventListener(air.SecurityErrorEvent.SECURITY_ERROR, doError)
  1098. loader.addEventListener(air.IOErrorEvent.IO_ERROR, doError)
  1099. loader.load(request)
  1100. }
  1101.  
  1102. function checkForLiveLogChanges()
  1103. {
  1104. currentTimeout = 0
  1105. setErrorText('')
  1106.  
  1107. var logFile = file.resolvePath("WoWCombatLog.txt")
  1108. var logFileExists = logFile && logFile.exists
  1109. var logFileSize = logFileExists ? logFile.size : 0
  1110.  
  1111. if (!logFile || !logFileExists || logFile.modificationDate.getTime() == liveLogLastModified || liveLogPosition == logFileSize) {
  1112. if (debugMode)
  1113. logToDebugPanel("No changes encountered. Our position is " + liveLogPosition + " and the file's size is " + logFileSize + ".")
  1114. unchangedCount++
  1115. if (unchangedCount == 24) { // 120 seconds more or less.
  1116. pushLogFight(false)
  1117. if (logFights.length) {
  1118. setProgressStatusText("Assuming combat ended. Compressing Combat Log Data", "livelog-progress-status")
  1119. currentTimeout = setTimeout(compressReport, 200)
  1120. return
  1121. }
  1122. }
  1123. currentTimeout = setTimeout(checkForLiveLogChanges, liveLogChangeInterval)
  1124. return
  1125. }
  1126.  
  1127. unchangedCount = 0
  1128.  
  1129. liveLogLastModified = logFile.modificationDate.getTime()
  1130.  
  1131. if (debugMode)
  1132. logToDebugPanel("File changed! Our position is " + liveLogPosition + " and the file's size is " + logFile.size + ".")
  1133.  
  1134. logStream = new LargeAsyncFileReader()
  1135. logStream.openAsync(logFile, air.FileMode.READ)
  1136. logStream.seek(liveLogPosition)
  1137.  
  1138. setProgressStatusText("Reading new combat log data", "livelog-progress-status")
  1139. currentTimeout = setTimeout(readFileChunk, 0)
  1140. }
  1141.  
  1142. function directorySelected(evt)
  1143. {
  1144. document.getElementById('directory').innerText = file.nativePath
  1145. setFileDisplay(file.nativePath, 'directory-display')
  1146.  
  1147. try {
  1148. baDirectory = new air.ByteArray
  1149. baDirectory.writeUTFBytes(file.nativePath)
  1150. air.EncryptedLocalStore.setItem('directory', baDirectory)
  1151. } catch (e) {
  1152. }
  1153.  
  1154. file = null
  1155. }
  1156.  
  1157. function setFileDisplay(str, id)
  1158. {
  1159. if (str.length > 70)
  1160. str = str.substr(0, 10) + '...' + str.substr(str.length-50, str.length);
  1161.  
  1162. document.getElementById(id).innerText = str;
  1163. }
  1164.  
  1165. function fileSelected(evt)
  1166. {
  1167. document.getElementById('logfile').innerText = file.nativePath
  1168. setFileDisplay(file.nativePath, 'logfile-display')
  1169.  
  1170. try {
  1171. baFile = new air.ByteArray
  1172. baFile.writeUTFBytes(file.nativePath)
  1173. air.EncryptedLocalStore.setItem('file', baFile)
  1174. } catch (e) {
  1175. }
  1176.  
  1177. file = null
  1178. }
  1179.  
  1180. function browseForDirectory()
  1181. {
  1182. file = new air.File()
  1183. file.addEventListener(air.Event.SELECT, directorySelected)
  1184. file.browseForDirectory("Select the World of Warcraft Logs Directory")
  1185. }
  1186.  
  1187. function browseForFile()
  1188. {
  1189. file = new air.File()
  1190. file.addEventListener(air.Event.SELECT, fileSelected)
  1191. var filterArray = Array()
  1192. filterArray.push(new air.FileFilter("Log Files", "*.txt"))
  1193. file.browseForOpen("Select the log file to upload (usually WoWCombatLogs.txt)", filterArray)
  1194. }
  1195.  
  1196. function startLiveLoggingSession(description, directoryName)
  1197. {
  1198. if (file)
  1199. return
  1200.  
  1201. if (selectedGuild == 0 && selectedRegion <= 0) {
  1202. setErrorText("For personal logs, you must specify the region you are uploading to. Hit the <i>Choose...</i> button above and pick a region.");
  1203. file = null
  1204. return
  1205. }
  1206.  
  1207. fileForDeletionAndArchival = null
  1208.  
  1209. setErrorText('');
  1210.  
  1211. if (!directoryName) {
  1212. setErrorText("You must specify a log directory.")
  1213. return;
  1214. }
  1215.  
  1216. file = new air.File(directoryName);
  1217. if (!file || !file.exists) {
  1218. setErrorText("Invalid directory chosen.")
  1219. return;
  1220. }
  1221.  
  1222. var logFile = file.resolvePath("WoWCombatLog.txt")
  1223. var logFileExists = logFile && logFile.exists
  1224.  
  1225. liveLogPosition = logFileExists ? logFile.size : 0
  1226. liveLogLastModified = logFileExists ? logFile.modificationDate.getTime() : 0
  1227.  
  1228. if (debugMode)
  1229. logToDebugPanel("Beginning live log with position: " + liveLogPosition + " and last modified " + liveLogLastModified + ".")
  1230.  
  1231. try {
  1232. baVisibility = new air.ByteArray
  1233. baVisibility.writeUTFBytes(selectedPrivacy.toString())
  1234. air.EncryptedLocalStore.setItem('visibility', baVisibility)
  1235. } catch (e) {
  1236. }
  1237.  
  1238. liveLogging = true
  1239.  
  1240. var loadingStr = '<img id="button-spinny" src="img/spinny.gif">'
  1241. document.getElementById('upload-button').innerHTML = loadingStr
  1242.  
  1243. currentTimeout = setTimeout(createReport, 0)
  1244. }
  1245.  
  1246. function escapedISOString(date)
  1247. {
  1248. var result = date.toISOString()
  1249. var replacedResult = result.replace(/:/g, "-")
  1250. return replacedResult
  1251. }
  1252.  
  1253. function createNewSplitFile() {
  1254. splitFileStream && (splitFileStream.close(), splitFileStream = null);
  1255. var e, t = file.name, i = t.lastIndexOf("."), o = i > -1, r = "";
  1256. o ? (e = t.substring(0, i), r = t.substring(i)) : e = t;
  1257. var n = new air.File(file.parent.nativePath).resolvePath(e + "-split-" + escapedISOString(new Date(splitFileTimestamp)) + r);
  1258. splitFileStream = new air.FileStream(), splitFileStream.open(n, air.FileMode.WRITE);
  1259. }
  1260.  
  1261. function splitLogFile(filename) {
  1262. if (file)
  1263. return
  1264.  
  1265. fileForDeletionAndArchival = null
  1266.  
  1267. setErrorText('');
  1268.  
  1269. if (!filename) {
  1270. setErrorText("You must specify a file.")
  1271. return;
  1272. }
  1273.  
  1274. file = new air.File(filename);
  1275. if (!file || !file.exists) {
  1276. setErrorText("Invalid file chosen.")
  1277. file = null
  1278. return
  1279. }
  1280.  
  1281. setProgressStatusText("Splitting Log File", "logfile-progress-status")
  1282. updateProgress(0, "logfile-progress")
  1283. selectReportPage("progress")
  1284.  
  1285. splittingLogFile = true
  1286. currentTimeout = setTimeout(openLogFile, 0)
  1287. }
  1288.  
  1289. function scanLogFileForRaids(filename) {
  1290. if (file)
  1291. return
  1292.  
  1293. fileForDeletionAndArchival = null
  1294.  
  1295. setErrorText('');
  1296.  
  1297. if (!filename) {
  1298. setErrorText("You must specify a file.")
  1299. return;
  1300. }
  1301.  
  1302. file = new air.File(filename);
  1303. if (!file || !file.exists) {
  1304. setErrorText("Invalid file chosen.")
  1305. file = null
  1306. return
  1307. }
  1308.  
  1309. try {
  1310. baVisibility = new air.ByteArray
  1311. baVisibility.writeUTFBytes(selectedPrivacy.toString())
  1312. air.EncryptedLocalStore.setItem('visibility', baVisibility)
  1313.  
  1314. baChooseFights = new air.ByteArray
  1315. baChooseFights.writeUTFBytes(document.getElementById('fight-chooser').checked ? '1' : '0')
  1316.  
  1317. air.EncryptedLocalStore.setItem('choosefights', baChooseFights)
  1318. } catch (e) {
  1319. }
  1320.  
  1321. setProgressStatusText("Scanning Log File For Raids", "logfile-progress-status")
  1322. updateProgress(0, "logfile-progress")
  1323. selectReportPage("progress")
  1324.  
  1325. scanningLogFileForRaids = true
  1326. currentTimeout = setTimeout(openLogFile, 0)
  1327. }
  1328.  
  1329. function deleteLogFile() {
  1330. var result = confirm("Are you sure you want to delete " + fileForDeletionAndArchival.name + "?");
  1331. if (!result || !fileForDeletionAndArchival)
  1332. return
  1333.  
  1334. try {
  1335. fileForDeletionAndArchival.deleteFile();
  1336. alert(fileForDeletionAndArchival.name + " successfully deleted.");
  1337. fileForDeletionAndArchival = null;
  1338. } catch (e) {
  1339. alert("Deletion of " + fileForDeletionAndArchival.name + " failed. Log out of WoW and try again.");
  1340. }
  1341. }
  1342.  
  1343. function archiveLogFile() {
  1344. var result = confirm("Are you sure you want to archive " + fileForDeletionAndArchival.name + "?");
  1345. if (!result || !fileForDeletionAndArchival)
  1346. return
  1347. try {
  1348. var e, t = fileForDeletionAndArchival.name, i = t.lastIndexOf("."), o = i > -1, r = "";
  1349. o ? (e = t.substring(0, i), r = t.substring(i)) : e = t;
  1350. var n = fileForDeletionAndArchival.parent.resolvePath("warcraftlogsarchive/" + e + "-archive-" + escapedISOString(new Date()) + r), l = n.parent;
  1351. l.createDirectory(), fileForDeletionAndArchival.moveTo(n, !0);
  1352. alert(fileForDeletionAndArchival.name + " successfully archived.");
  1353. fileForDeletionAndArchival = null;
  1354. } catch (a) {
  1355. alert("Archival of " + fileForDeletionAndArchival.name + " failed. Log out of WoW and try again.");
  1356. }
  1357. }
  1358.  
  1359. var currentPage = "first"
  1360.  
  1361. function selectReportPage(page) {
  1362. document.getElementById('report-' + currentPage + "-page").style.display = 'none'
  1363. document.getElementById('report-' + page + "-page").style.display = 'block'
  1364. currentPage = page
  1365. }
  1366.  
  1367. function setReportUIElementsVisibility(mode, visible)
  1368. {
  1369. if (mode == "upload") {
  1370. if (visible) {
  1371. document.getElementById('file-chooser-description').style.display = ''
  1372. document.getElementById('file-chooser-row').style.display = ''
  1373. document.getElementById('fight-chooser-container').style.visibility = ''
  1374. document.getElementById('logfile-progress-container').style.display = ''
  1375. document.getElementById('guild-chooser-description').style.display = ''
  1376. document.getElementById('guild-chooser-controls').style.display = ''
  1377. document.getElementById('view-report-description').style.display = ''
  1378. document.getElementById('view-report-container').style.display = ''
  1379. document.getElementById('description-label').style.display = ''
  1380. } else {
  1381. document.getElementById('file-chooser-description').style.display = 'none'
  1382. document.getElementById('file-chooser-row').style.display = 'none'
  1383. document.getElementById('fight-chooser-container').style.visibility = 'hidden'
  1384. document.getElementById('logfile-progress-container').style.display = 'none'
  1385. document.getElementById('guild-chooser-description').style.display = 'none'
  1386. document.getElementById('guild-chooser-controls').style.display = 'none'
  1387. document.getElementById('view-report-description').style.display = 'none'
  1388. document.getElementById('view-report-container').style.display = 'none'
  1389. document.getElementById('description-label').style.display = 'none'
  1390. }
  1391. } else if (mode == "livelog") {
  1392. if (visible) {
  1393. document.getElementById('directory-chooser-description').style.display = ''
  1394. document.getElementById('directory-chooser-row').style.display = ''
  1395. document.getElementById('livelog-progress-status').style.display = ''
  1396. document.getElementById('endlivelogbutton').style.display = ''
  1397. document.getElementById('viewlivelogbutton').style.display = ''
  1398. document.getElementById('guild-chooser-description').style.display = ''
  1399. document.getElementById('guild-chooser-controls').style.display = ''
  1400. document.getElementById('view-report-description').style.display = ''
  1401. document.getElementById('view-report-container').style.display = ''
  1402. document.getElementById('description-label').style.display = ''
  1403. } else {
  1404. document.getElementById('directory-chooser-description').style.display = 'none'
  1405. document.getElementById('directory-chooser-row').style.display = 'none'
  1406. document.getElementById('livelog-progress-status').style.display = 'none'
  1407. document.getElementById('endlivelogbutton').style.display = 'none'
  1408. document.getElementById('viewlivelogbutton').style.display = 'none'
  1409. document.getElementById('guild-chooser-description').style.display = 'none'
  1410. document.getElementById('guild-chooser-controls').style.display = 'none'
  1411. document.getElementById('view-report-description').style.display = 'none'
  1412. document.getElementById('view-report-container').style.display = 'none'
  1413. document.getElementById('description-label').style.display = 'none'
  1414. }
  1415. } else if (mode == "split") {
  1416. if (visible) {
  1417. document.getElementById('split-file-chooser-description').style.display = ''
  1418. document.getElementById('file-chooser-row').style.display = ''
  1419. document.getElementById('logfile-progress-container').style.display = ''
  1420. document.getElementById('description-label').style.display = 'none'
  1421. } else {
  1422. document.getElementById('split-file-chooser-description').style.display = 'none'
  1423. document.getElementById('file-chooser-row').style.display = 'none'
  1424. document.getElementById('logfile-progress-container').style.display = 'none'
  1425. document.getElementById('description-label').style.display = ''
  1426. }
  1427. }
  1428. }
  1429.  
  1430. function setReportUIMode(mode)
  1431. {
  1432. if (mode == reportUIMode)
  1433. return
  1434.  
  1435. setReportUIElementsVisibility(reportUIMode, false)
  1436. reportUIMode = mode
  1437. setReportUIElementsVisibility(reportUIMode, true)
  1438. }
  1439.  
  1440. function goButtonClicked()
  1441. {
  1442. if (reportUIMode == "upload") {
  1443. var scanForFights = document.getElementById('fight-chooser').checked
  1444. if (scanForFights)
  1445. scanLogFileForRaids(document.getElementById('logfile').innerText)
  1446. else
  1447. processLogFile(document.getElementById('description').value, document.getElementById('logfile').innerText)
  1448. } else if (reportUIMode == "livelog")
  1449. startLiveLoggingSession(document.getElementById('description').value, document.getElementById('directory').innerText)
  1450. else if (reportUIMode == "split")
  1451. splitLogFile(document.getElementById('logfile').innerText)
  1452. }
  1453.  
  1454. function fightsButtonClicked()
  1455. {
  1456. var options = document.getElementById('fights-list').options
  1457. var selectedOptions = new Array()
  1458. for (var i = 0; i < options.length; ++i) {
  1459. if (options[i].selected)
  1460. selectedOptions.push(options[i])
  1461. }
  1462.  
  1463. if (selectedOptions.length == 0) {
  1464. setErrorText("You must select at least one fight to upload.")
  1465. return
  1466. }
  1467.  
  1468. var raidsToCheck = scannedRaids
  1469. cancelOrFinish('fights') // This wipes out scannedRaids and clears raidsToUpload.
  1470.  
  1471. for (var i = 0; i < selectedOptions.length; ++i)
  1472. raidsToUpload.push(raidsToCheck[selectedOptions[i].value])
  1473.  
  1474. processLogFile(document.getElementById('description').value, document.getElementById('logfile').innerText)
  1475. }
  1476.  
  1477. var returnPage = null
  1478.  
  1479. function showSelectGuildUI() {
  1480. returnPage = currentPage
  1481. setErrorText('')
  1482. selectReportPage('guild')
  1483. }
  1484.  
  1485. function buildGuilds()
  1486. {
  1487. document.getElementById('guilds-container').innerHTML = guildList
  1488. var guildID = storedGuild != '' ? parseInt(storedGuild) : 0
  1489. var teamID = storedTeamID != '' ? parseInt(storedTeamID) : 0
  1490. selectGuild(guildID)
  1491. if (teamID !== '')
  1492. selectTeam(parseInt(teamID))
  1493. else
  1494. selectTeam(0)
  1495. }
  1496.  
  1497. var selectedGuild = undefined
  1498.  
  1499. function selectGuildOrRegionByTarget(event)
  1500. {
  1501. var node = event.target
  1502. var guildAttr = node.getAttribute("guildid")
  1503. var regionAttr = node.getAttribute("regionid")
  1504. var teamAttr = node.getAttribute('teamid')
  1505. while (guildAttr === null && regionAttr === null && teamAttr === null && node) {
  1506. node = node.parentNode
  1507. guildAttr = node.getAttribute("guildid")
  1508. regionAttr = node.getAttribute("regionid")
  1509. teamAttr = node.getAttribute('teamid')
  1510. }
  1511. if (guildAttr !== null)
  1512. selectGuild(parseInt(guildAttr))
  1513. else if (regionAttr !== null)
  1514. selectRegion(parseInt(regionAttr))
  1515. else if (teamAttr !== null)
  1516. selectTeam(parseInt(teamAttr))
  1517. }
  1518.  
  1519. function selectRegion(regionID)
  1520. {
  1521. if (selectedRegion > 0)
  1522. document.getElementById('region-' + selectedRegion).removeAttribute("selected")
  1523.  
  1524. document.getElementById('region-' + regionID).setAttribute("selected", true)
  1525.  
  1526. try {
  1527. baRegionID = new air.ByteArray
  1528. baRegionID.writeUTFBytes(regionID)
  1529. air.EncryptedLocalStore.setItem('region', baRegionID)
  1530. } catch (e) {
  1531. }
  1532.  
  1533. selectedRegion = regionID
  1534. }
  1535.  
  1536. function selectTeam(teamID)
  1537. {
  1538. if (selectedGuild == 0)
  1539. return
  1540.  
  1541. document.getElementById('teams-' + selectedGuild + '-' + selectedTeam).removeAttribute("selected")
  1542.  
  1543. document.getElementById('teams-' + selectedGuild + '-' + teamID).setAttribute("selected", true)
  1544.  
  1545. try {
  1546. baTeamID = new air.ByteArray
  1547. baTeamID.writeUTFBytes(teamID)
  1548. air.EncryptedLocalStore.setItem('team', baTeamID)
  1549. } catch (e) {
  1550. }
  1551.  
  1552. selectedTeam = teamID
  1553. }
  1554.  
  1555. function selectGuild(guildID)
  1556. {
  1557. if (selectedGuild !== undefined) {
  1558. document.getElementById('guild-' + selectedGuild).removeAttribute("selected")
  1559.  
  1560. // Hide that guild's raid teams.
  1561. if (selectedGuild > 0) {
  1562. document.getElementById('teams-' + selectedGuild).style.display = 'none'
  1563. selectTeam(0)
  1564. }
  1565. }
  1566.  
  1567. document.getElementById('guild-' + guildID).setAttribute("selected", true)
  1568.  
  1569. document.getElementById('selected-guild-upload').innerHTML = document.getElementById('guild-' + guildID).innerHTML
  1570.  
  1571. try {
  1572. baGuild = new air.ByteArray
  1573. baGuild.writeUTFBytes(guildID)
  1574. air.EncryptedLocalStore.setItem('guild', baGuild)
  1575. } catch (e) {
  1576. }
  1577.  
  1578. selectedGuild = guildID
  1579.  
  1580. if (selectedGuild === 0)
  1581. document.getElementById('regions').style.display = ''
  1582. else {
  1583. document.getElementById('regions').style.display = 'none'
  1584.  
  1585. // Show this guild's teams.
  1586. document.getElementById('teams-' + selectedGuild).style.display = ''
  1587.  
  1588. selectTeam(0)
  1589. }
  1590. }
  1591.  
  1592. function finalizeGuild() {
  1593. selectReportPage(returnPage)
  1594. }
  1595.  
  1596. function showFightSelectionUI()
  1597. {
  1598. selectReportPage('fights')
  1599. rebuildFights()
  1600. }
  1601.  
  1602. function includeTrashChanged()
  1603. {
  1604. rebuildFights()
  1605. }
  1606.  
  1607. function printDuration(duration)
  1608. {
  1609. duration = Math.floor(duration / 1000)
  1610. var result = ''
  1611. var hours = Math.floor(duration / 3600)
  1612. var minutes = Math.floor((duration % 3600) / 60)
  1613. var seconds = duration % 60
  1614. var putZeroInMinutes = false
  1615. if (hours > 0) {
  1616. putZeroInMinutes = true
  1617. result += hours + ":"
  1618. }
  1619. result += (putZeroInMinutes && minutes < 10 ? "0" : '') + minutes + ":" + (seconds < 10 ? "0" : '') + seconds
  1620. return result
  1621. }
  1622.  
  1623. function printDate(time)
  1624. {
  1625. var date = new Date(time)
  1626. return date.toLocaleString()
  1627. }
  1628.  
  1629. function optionHovered(evt)
  1630. {
  1631. var raid = scannedRaids[this.value]
  1632. var details = document.getElementById('fight-details')
  1633. var result = "<b>" + raid.name + "</b><br>"
  1634. result += "<b>Date:</b> " + printDate(raid.start) + "<br>"
  1635. result += "<b>Duration:</b> " + printDuration(raid.end - raid.start) + "<br>"
  1636. var friendliesArray = new Array()
  1637. for (var k in raid.friendlies) {
  1638. if (raid.friendlies.hasOwnProperty(k))
  1639. friendliesArray.push(k)
  1640. }
  1641. var enemiesArray = new Array()
  1642. for (var k in raid.enemies) {
  1643. if (raid.enemies.hasOwnProperty(k))
  1644. enemiesArray.push(k)
  1645. }
  1646. friendliesArray.sort()
  1647. enemiesArray.sort()
  1648.  
  1649. result += "<b>Player Participants:</b> "
  1650. for (var i = 0; i < friendliesArray.length; ++i) {
  1651. if (i > 0)
  1652. result += ", "
  1653. result += friendliesArray[i]
  1654. }
  1655. result += "<br>"
  1656. result += "<b>Enemy Participants:</b> "
  1657. for (var i = 0; i < enemiesArray.length; ++i) {
  1658. if (i > 0)
  1659. result += ", "
  1660. result += enemiesArray[i]
  1661. }
  1662. result += "<br>"
  1663. details.innerHTML = result
  1664. }
  1665.  
  1666. function optionUnhovered(evt)
  1667. {
  1668. var details = document.getElementById('fight-details')
  1669. details.innerHTML = "Hover over enemy names in the list to the left to see details about the fights in this box."
  1670. }
  1671.  
  1672. function nameForDifficulty(difficulty)
  1673. {
  1674. if (difficulty == 16)
  1675. return "Mythic"
  1676. if (difficulty == 7 || difficulty == 17)
  1677. return "LFR"
  1678. if (difficulty == 14)
  1679. return logVersion == 1 ? "Flex" : "Normal"
  1680. if (difficulty == 15)
  1681. return "Heroic"
  1682. if (difficulty == 8)
  1683. return logVersion >= 7 ? "Mythic+" : "CM"
  1684. if (difficulty == 1 || difficulty == 3 || difficulty == 4 || difficulty == 12 || difficulty == 9)
  1685. return "Normal"
  1686. if (difficulty == 2 || difficulty == 5 || difficulty == 6 || difficulty == 11)
  1687. return "Heroic"
  1688. return "";
  1689. }
  1690.  
  1691. function rebuildFights()
  1692. {
  1693. var fightList = document.getElementById('fights-list')
  1694. fightList.innerHTML = ''
  1695. var includeTrash = document.getElementById('include-trash').checked
  1696. for (var i = 0; i < scannedRaids.length; ++i) {
  1697. if (!includeTrash && scannedRaids[i].boss == 0)
  1698. continue
  1699. var option = document.createElement("option")
  1700. option.value = i
  1701. option.onmouseover = optionHovered
  1702. option.onmouseout = optionUnhovered
  1703. var name = scannedRaids[i].name
  1704. if (scannedRaids[i].boss > 0) {
  1705. name += " " + nameForDifficulty(scannedRaids[i].difficulty)
  1706. option.setAttribute('class', 'Boss')
  1707. if (!scannedRaids[i].success)
  1708. name += " Wipe"
  1709. else
  1710. name += " Kill"
  1711. if (scannedRaids[i].pulls > 1)
  1712. name += "s (" + scannedRaids[i].pulls + ")"
  1713. } else
  1714. option.setAttribute('class', 'NPC')
  1715. option.text = name
  1716. fightList.add(option, null)
  1717. }
  1718. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement