|
1 |
| -"use strict"; |
2 |
| - |
3 |
| -/* |
4 |
| - * Credits to rDacted [2670953] (https://www.torn.com/profiles.php?XID=2670953). |
5 |
| - * |
6 |
| - * Applicable to almost everything beyond this point. |
7 |
| - */ |
8 |
| - |
9 |
| -(async () => { |
10 |
| - if (!getPageStatus().access) return; |
11 |
| - |
12 |
| - const BLUE_ARROW = chrome.runtime.getURL("resources/images/svg-icons/blue-arrow.svg"); |
13 |
| - const GREEN_ARROW = chrome.runtime.getURL("resources/images/svg-icons/green-arrow.svg"); |
14 |
| - const RED_ARROW = chrome.runtime.getURL("resources/images/svg-icons/red-arrow.svg"); |
15 |
| - |
16 |
| - let scoutLock = false; |
17 |
| - |
18 |
| - const feature = featureManager.registerFeature( |
19 |
| - "FF Scouter Gauge", |
20 |
| - "ff-scouter", |
21 |
| - () => settings.scripts.ffScouter.gauge, |
22 |
| - initialise, |
23 |
| - triggerGauge, |
24 |
| - removeGauge, |
25 |
| - { |
26 |
| - storage: ["settings.scripts.ffScouter.gauge", "settings.external.tornpal"], |
27 |
| - }, |
28 |
| - () => { |
29 |
| - if (!hasAPIData()) return "No API access."; |
30 |
| - else if (!settings.external.tornpal) return "TornPal not enabled"; |
31 |
| - } |
32 |
| - ); |
33 |
| - |
34 |
| - function initialise() { |
35 |
| - new MutationObserver(function () { |
36 |
| - if (!feature.enabled()) return; |
37 |
| - |
38 |
| - setTimeout(triggerGauge); |
39 |
| - }).observe(document, { attributes: false, childList: true, characterData: false, subtree: true }); |
40 |
| - } |
41 |
| - |
42 |
| - async function triggerGauge() { |
43 |
| - if (scoutLock) return; |
44 |
| - scoutLock = true; |
45 |
| - |
46 |
| - const honorBars = [...document.findAll(".honor-text-wrap")]; |
47 |
| - if (honorBars.length > 0) { |
48 |
| - applyGauge(honorBars).finally(() => (scoutLock = false)); |
49 |
| - } else { |
50 |
| - let selector; |
51 |
| - |
52 |
| - switch (getPage()) { |
53 |
| - case "factions": |
54 |
| - selector = ".member"; |
55 |
| - break; |
56 |
| - case "companies": |
57 |
| - case "joblist": |
58 |
| - selector = ".employee"; |
59 |
| - break; |
60 |
| - case "messages": |
61 |
| - case "abroad-people": |
62 |
| - case "hospital": |
63 |
| - case "userlist": |
64 |
| - selector = ".name"; |
65 |
| - break; |
66 |
| - case "bounties": |
67 |
| - selector = ".target, .listed"; |
68 |
| - break; |
69 |
| - case "forums": |
70 |
| - selector = ".last-poster, .starter, .last-post,.poster"; |
71 |
| - break; |
72 |
| - case "hof": |
73 |
| - selector = "[class^=''userInfoBox__']"; |
74 |
| - break; |
75 |
| - default: |
76 |
| - return; |
77 |
| - } |
78 |
| - |
79 |
| - applyGauge([...document.findAll(selector)]).finally(() => (scoutLock = false)); |
80 |
| - } |
81 |
| - } |
82 |
| - |
83 |
| - function applyGauge(elements) { |
84 |
| - elements = elements |
85 |
| - .filter((element) => !element.classList.contains("tt-ff-scouter-indicator")) |
86 |
| - .map((element) => ({ element, id: extractPlayerId(element) })) |
87 |
| - .filter(({ id }) => !!id); |
88 |
| - if (elements.length === 0) return Promise.resolve(); |
89 |
| - |
90 |
| - return new Promise((resolve) => { |
91 |
| - scoutFFGroup(elements.map(({ id }) => id)).then((scouts) => { |
92 |
| - if (!scouts.status) { |
93 |
| - resolve(); |
94 |
| - return; |
95 |
| - } |
96 |
| - |
97 |
| - for (const { element, id } of elements) { |
98 |
| - element.classList.add("tt-ff-scouter-indicator"); |
99 |
| - if (!element.classList.contains("indicator-lines")) { |
100 |
| - element.classList.remove("small", "big"); |
101 |
| - element.classList.add("indicator-lines"); |
102 |
| - element.style.setProperty("--arrow-width", "20px"); |
103 |
| - } |
104 |
| - |
105 |
| - const ff = scouts.results[id]?.result?.value; |
106 |
| - if (ff) { |
107 |
| - const percent = convertFFToPercentage(ff); |
108 |
| - element.style.setProperty("--band-percent", percent); |
109 |
| - |
110 |
| - element.find(".tt-ff-scouter-arrow")?.remove(); |
111 |
| - |
112 |
| - let arrow; |
113 |
| - if (percent < 33) { |
114 |
| - arrow = BLUE_ARROW; |
115 |
| - } else if (percent < 66) { |
116 |
| - arrow = GREEN_ARROW; |
117 |
| - } else { |
118 |
| - arrow = RED_ARROW; |
119 |
| - } |
120 |
| - |
121 |
| - element.appendChild( |
122 |
| - document.newElement({ |
123 |
| - type: "img", |
124 |
| - class: "tt-ff-scouter-arrow", |
125 |
| - attributes: { src: arrow }, |
126 |
| - }) |
127 |
| - ); |
128 |
| - } |
129 |
| - } |
130 |
| - |
131 |
| - resolve(); |
132 |
| - }); |
133 |
| - }); |
134 |
| - } |
135 |
| - |
136 |
| - function extractPlayerId(element) { |
137 |
| - const match = element.parentElement?.href?.match(/.*XID=(?<target_id>\d+)/); |
138 |
| - if (match) { |
139 |
| - return match.groups.target_id; |
140 |
| - } |
141 |
| - |
142 |
| - const anchors = element.getElementsByTagName("a"); |
143 |
| - |
144 |
| - for (const anchor of anchors) { |
145 |
| - const match = anchor.href.match(/.*XID=(?<target_id>\d+)/); |
146 |
| - if (match) { |
147 |
| - return match.groups.target_id; |
148 |
| - } |
149 |
| - } |
150 |
| - |
151 |
| - if (element.nodeName.toLowerCase() === "a") { |
152 |
| - const match = element.href.match(/.*XID=(?<target_id>\d+)/); |
153 |
| - if (match) { |
154 |
| - return match.groups.target_id; |
155 |
| - } |
156 |
| - } |
157 |
| - |
158 |
| - return null; |
159 |
| - } |
160 |
| - |
161 |
| - function convertFFToPercentage(ff) { |
162 |
| - ff = Math.min(ff, 8); |
163 |
| - // There are 3 key areas, low, medium, high |
164 |
| - // Low is 1-2 |
165 |
| - // Medium is 2-4 |
166 |
| - // High is 4+ |
167 |
| - // If we clip high at 8 then the math becomes easy |
168 |
| - // The percent is 0-33% 33-66% 66%-100% |
169 |
| - const lowPoint = 2; |
170 |
| - const highPoint = 4; |
171 |
| - const lowMidPercent = 33; |
172 |
| - const midHighPercent = 66; |
173 |
| - |
174 |
| - let percent; |
175 |
| - if (ff < lowPoint) { |
176 |
| - percent = ((ff - 1) / (lowPoint - 1)) * lowMidPercent; |
177 |
| - } else if (ff < highPoint) { |
178 |
| - percent = ((ff - lowPoint) / (highPoint - lowPoint)) * (midHighPercent - lowMidPercent) + lowMidPercent; |
179 |
| - } else { |
180 |
| - percent = ((ff - highPoint) / (8 - highPoint)) * (100 - midHighPercent) + midHighPercent; |
181 |
| - } |
182 |
| - |
183 |
| - return percent; |
184 |
| - } |
185 |
| - |
186 |
| - function removeGauge() { |
187 |
| - document.findAll(".tt-ff-scouter-indicator").forEach((element) => element.classList.remove("tt-ff-scouter-indicator")); |
188 |
| - document.findAll(".tt-ff-scouter-arrow").forEach((element) => element.remove()); |
189 |
| - } |
190 |
| -})(); |
| 1 | +"use strict"; |
| 2 | + |
| 3 | +/* |
| 4 | + * Credits to rDacted [2670953] (https://www.torn.com/profiles.php?XID=2670953). |
| 5 | + * |
| 6 | + * Applicable to almost everything beyond this point. |
| 7 | + */ |
| 8 | + |
| 9 | +(async () => { |
| 10 | + if (!getPageStatus().access) return; |
| 11 | + |
| 12 | + const BLUE_ARROW = chrome.runtime.getURL("resources/images/svg-icons/blue-arrow.svg"); |
| 13 | + const GREEN_ARROW = chrome.runtime.getURL("resources/images/svg-icons/green-arrow.svg"); |
| 14 | + const RED_ARROW = chrome.runtime.getURL("resources/images/svg-icons/red-arrow.svg"); |
| 15 | + |
| 16 | + let scoutLock = false; |
| 17 | + |
| 18 | + const feature = featureManager.registerFeature( |
| 19 | + "FF Scouter Gauge", |
| 20 | + "ff-scouter", |
| 21 | + () => settings.scripts.ffScouter.gauge, |
| 22 | + initialise, |
| 23 | + triggerGauge, |
| 24 | + removeGauge, |
| 25 | + { |
| 26 | + storage: ["settings.scripts.ffScouter.gauge", "settings.external.tornpal"], |
| 27 | + }, |
| 28 | + () => { |
| 29 | + if (!hasAPIData()) return "No API access."; |
| 30 | + else if (!settings.external.tornpal) return "TornPal not enabled"; |
| 31 | + } |
| 32 | + ); |
| 33 | + |
| 34 | + function initialise() { |
| 35 | + new MutationObserver(function () { |
| 36 | + if (!feature.enabled()) return; |
| 37 | + |
| 38 | + setTimeout(triggerGauge); |
| 39 | + }).observe(document, { attributes: false, childList: true, characterData: false, subtree: true }); |
| 40 | + } |
| 41 | + |
| 42 | + async function triggerGauge() { |
| 43 | + if (scoutLock) return; |
| 44 | + scoutLock = true; |
| 45 | + |
| 46 | + const honorBars = [...document.findAll(".honor-text-wrap")]; |
| 47 | + if (honorBars.length > 0) { |
| 48 | + applyGauge(honorBars).finally(() => (scoutLock = false)); |
| 49 | + } else { |
| 50 | + let selector; |
| 51 | + |
| 52 | + switch (getPage()) { |
| 53 | + case "factions": |
| 54 | + selector = ".member"; |
| 55 | + break; |
| 56 | + case "companies": |
| 57 | + case "joblist": |
| 58 | + selector = ".employee"; |
| 59 | + break; |
| 60 | + case "messages": |
| 61 | + case "abroad-people": |
| 62 | + case "hospital": |
| 63 | + case "userlist": |
| 64 | + selector = ".name"; |
| 65 | + break; |
| 66 | + case "bounties": |
| 67 | + selector = ".target, .listed"; |
| 68 | + break; |
| 69 | + case "forums": |
| 70 | + selector = ".last-poster, .starter, .last-post,.poster"; |
| 71 | + break; |
| 72 | + case "hof": |
| 73 | + selector = "[class^=''userInfoBox__']"; |
| 74 | + break; |
| 75 | + default: |
| 76 | + scoutLock = false; |
| 77 | + return; |
| 78 | + } |
| 79 | + |
| 80 | + applyGauge([...document.findAll(selector)]).finally(() => (scoutLock = false)); |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + function applyGauge(elements) { |
| 85 | + elements = elements |
| 86 | + .filter((element) => !element.classList.contains("tt-ff-scouter-indicator")) |
| 87 | + .map((element) => ({ element, id: extractPlayerId(element) })) |
| 88 | + .filter(({ id }) => !!id); |
| 89 | + if (elements.length === 0) return Promise.resolve(); |
| 90 | + |
| 91 | + return new Promise((resolve) => { |
| 92 | + scoutFFGroup(elements.map(({ id }) => id)).then((scouts) => { |
| 93 | + if (!scouts.status) { |
| 94 | + resolve(); |
| 95 | + return; |
| 96 | + } |
| 97 | + |
| 98 | + for (const { element, id } of elements) { |
| 99 | + element.classList.add("tt-ff-scouter-indicator"); |
| 100 | + if (!element.classList.contains("indicator-lines")) { |
| 101 | + element.classList.remove("small", "big"); |
| 102 | + element.classList.add("indicator-lines"); |
| 103 | + element.style.setProperty("--arrow-width", "20px"); |
| 104 | + } |
| 105 | + |
| 106 | + const ff = scouts.results[id]?.result?.value; |
| 107 | + if (ff) { |
| 108 | + const percent = convertFFToPercentage(ff); |
| 109 | + element.style.setProperty("--band-percent", percent); |
| 110 | + |
| 111 | + element.find(".tt-ff-scouter-arrow")?.remove(); |
| 112 | + |
| 113 | + let arrow; |
| 114 | + if (percent < 33) { |
| 115 | + arrow = BLUE_ARROW; |
| 116 | + } else if (percent < 66) { |
| 117 | + arrow = GREEN_ARROW; |
| 118 | + } else { |
| 119 | + arrow = RED_ARROW; |
| 120 | + } |
| 121 | + |
| 122 | + element.appendChild( |
| 123 | + document.newElement({ |
| 124 | + type: "img", |
| 125 | + class: "tt-ff-scouter-arrow", |
| 126 | + attributes: { src: arrow }, |
| 127 | + }) |
| 128 | + ); |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | + resolve(); |
| 133 | + }); |
| 134 | + }); |
| 135 | + } |
| 136 | + |
| 137 | + function extractPlayerId(element) { |
| 138 | + const match = element.parentElement?.href?.match(/.*XID=(?<target_id>\d+)/); |
| 139 | + if (match) { |
| 140 | + return match.groups.target_id; |
| 141 | + } |
| 142 | + |
| 143 | + const anchors = element.getElementsByTagName("a"); |
| 144 | + |
| 145 | + for (const anchor of anchors) { |
| 146 | + const match = anchor.href.match(/.*XID=(?<target_id>\d+)/); |
| 147 | + if (match) { |
| 148 | + return match.groups.target_id; |
| 149 | + } |
| 150 | + } |
| 151 | + |
| 152 | + if (element.nodeName.toLowerCase() === "a") { |
| 153 | + const match = element.href.match(/.*XID=(?<target_id>\d+)/); |
| 154 | + if (match) { |
| 155 | + return match.groups.target_id; |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + return null; |
| 160 | + } |
| 161 | + |
| 162 | + function convertFFToPercentage(ff) { |
| 163 | + ff = Math.min(ff, 8); |
| 164 | + // There are 3 key areas, low, medium, high |
| 165 | + // Low is 1-2 |
| 166 | + // Medium is 2-4 |
| 167 | + // High is 4+ |
| 168 | + // If we clip high at 8 then the math becomes easy |
| 169 | + // The percent is 0-33% 33-66% 66%-100% |
| 170 | + const lowPoint = 2; |
| 171 | + const highPoint = 4; |
| 172 | + const lowMidPercent = 33; |
| 173 | + const midHighPercent = 66; |
| 174 | + |
| 175 | + let percent; |
| 176 | + if (ff < lowPoint) { |
| 177 | + percent = ((ff - 1) / (lowPoint - 1)) * lowMidPercent; |
| 178 | + } else if (ff < highPoint) { |
| 179 | + percent = ((ff - lowPoint) / (highPoint - lowPoint)) * (midHighPercent - lowMidPercent) + lowMidPercent; |
| 180 | + } else { |
| 181 | + percent = ((ff - highPoint) / (8 - highPoint)) * (100 - midHighPercent) + midHighPercent; |
| 182 | + } |
| 183 | + |
| 184 | + return percent; |
| 185 | + } |
| 186 | + |
| 187 | + function removeGauge() { |
| 188 | + document.findAll(".tt-ff-scouter-indicator").forEach((element) => element.classList.remove("tt-ff-scouter-indicator")); |
| 189 | + document.findAll(".tt-ff-scouter-arrow").forEach((element) => element.remove()); |
| 190 | + } |
| 191 | +})(); |
0 commit comments