Greasy Fork 还支持 简体中文。

KDE Store: Graphs

Misc

目前為 2018-10-09 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name KDE Store: Graphs
  3. // @namespace https://github.com/Zren/
  4. // @description Misc
  5. // @icon https://store.kde.org/images_sys/store_logo/kde-store.ico
  6. // @author Zren
  7. // @version 5
  8. // @match https://www.opendesktop.org/member/*/plings*
  9. // @match https://www.opendesktop.org/u/*/plings*
  10. // @match https://store.kde.org/member/*/plings*
  11. // @match https://store.kde.org/u/*/plings*
  12. // @grant none
  13. // @require https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js
  14. // ==/UserScript==
  15.  
  16. var el = function(html) {
  17. var e = document.createElement('div');
  18. e.innerHTML = html;
  19. return e.removeChild(e.firstChild);
  20. }
  21.  
  22. function daysLeftMultiplier() {
  23. var now = new Date()
  24. var startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
  25. var endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1)
  26. var totalTime = endOfMonth.valueOf() - startOfMonth.valueOf()
  27. var timeProcessed = now.valueOf() - startOfMonth.valueOf()
  28. var timeLeft = endOfMonth.valueOf() - now.valueOf()
  29. if (timeProcessed == 0) {
  30. return 1
  31. } else {
  32. return 1 + (timeLeft / timeProcessed)
  33. }
  34.  
  35. //var timeLeftInMonth = timeLeft / totalTime
  36. // return 1 + timeLeftInMonth
  37.  
  38. if (timeLeftInMonth <= 0) {
  39. return 1
  40. } else {
  41. return totalTime / timeLeft
  42. }
  43.  
  44. }
  45.  
  46. function getProductDownloadsOverTime() {
  47. var currentMonthMultiplier = daysLeftMultiplier()
  48. var projectCurrentMonth = false
  49.  
  50. var graphData = {}
  51. var tabs = document.querySelectorAll('.tab-content .tab-pane')
  52. for (var i = 0; i < tabs.length; i++) {
  53. var tabPane = tabs[i]
  54. for (var row of tabPane.querySelectorAll('.row:not(.row-total')) {
  55. var productName = row.children[1].querySelector('span').textContent
  56. var productDownloads = row.children[2].querySelector('span').textContent
  57. //console.log('graphData', productName, productDownloads, parseInt(productDownloads, 10))
  58. productDownloads = parseInt(productDownloads, 10)
  59.  
  60. if (i == 0 && projectCurrentMonth) { // Current Month
  61. productDownloads = Math.round(productDownloads * currentMonthMultiplier)
  62. }
  63.  
  64. var productData = graphData[productName]
  65. if (!graphData[productName]) {
  66. productData = new Array(tabs.length).fill(0)
  67. /*
  68. for (var j = 0; j < i; j++) {
  69. productData[j] = null
  70. }
  71. */
  72. graphData[productName] = productData
  73. }
  74.  
  75. productData[i] = productDownloads
  76. }
  77. }
  78. return graphData
  79. }
  80. function randomColor() {
  81. // Based on the Random Pastel code from StackOverflow
  82. // https://stackoverflow.com/a/43195379/947742
  83. return "hsl(" + 360 * Math.random() + ', ' + // Hue: Any
  84. (25 + 70 * Math.random()) + '%, ' + // Saturation: 25-95
  85. (40 + 30 * Math.random()) + '%)'; // Lightness: 40-70
  86. }
  87.  
  88. // https://stackoverflow.com/a/44134328/947742
  89. function hslToRgb(h, s, l) {
  90. h /= 360;
  91. s /= 100;
  92. l /= 100;
  93. var r, g, b;
  94. if (s === 0) {
  95. r = g = b = l; // achromatic
  96. } else {
  97. function hue2rgb(p, q, t) {
  98. if (t < 0) t += 1;
  99. if (t > 1) t -= 1;
  100. if (t < 1 / 6) return p + (q - p) * 6 * t;
  101. if (t < 1 / 2) return q;
  102. if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
  103. return p;
  104. }
  105. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  106. var p = 2 * l - q;
  107. r = hue2rgb(p, q, h + 1 / 3);
  108. g = hue2rgb(p, q, h);
  109. b = hue2rgb(p, q, h - 1 / 3);
  110. }
  111. return { r:r, g:g, b:b }
  112. }
  113. function rgbToHex(c) {
  114. function toHex(x) {
  115. const hex = Math.round(x * 255).toString(16);
  116. return hex.length === 1 ? '0' + hex : hex;
  117. }
  118. return '#' + toHex(c.r) + toHex(c.g) + toHex(c.b)
  119. }
  120. function hslToHex(h, s, l) {
  121. var c = hslToRgb(h, s, l)
  122. function toHex(x) {
  123. const hex = Math.round(x * 255).toString(16);
  124. return hex.length === 1 ? '0' + hex : hex;
  125. }
  126. return '#' + toHex(c.r) + toHex(c.g) + toHex(c.b)
  127. }
  128. function rgbToRgba(c, a) {
  129. return 'rgba(' + Math.round(c.r * 255) + ', ' + Math.round(c.g * 255) + ', ' + Math.round(c.b * 255) + ', ' + a + ')'
  130. }
  131. function getPastelColor(i, n) {
  132. return hslToRgb(i / n * 360, 55, 70)
  133. }
  134.  
  135. function convertToDatasets(graphData) {
  136. var datasets = []
  137. var products = Object.keys(graphData)
  138. products.sort()
  139.  
  140. for (var i = 0; i < products.length; i++) {
  141. var productName = products[i]
  142. var productData = graphData[productName]
  143. var dataset = {}
  144. dataset.label = productName
  145. dataset.data = Array.from(productData).reverse()
  146. dataset.fill = false
  147. var datasetColor = getPastelColor(i, products.length)
  148. dataset.accentColor = rgbToHex(datasetColor)
  149. dataset.accentFadedColor = rgbToRgba(datasetColor, 0.2)
  150. dataset.backgroundColor = dataset.accentColor
  151. dataset.borderColor = dataset.accentColor
  152. dataset.lineTension = 0.1
  153. datasets.push(dataset)
  154. }
  155. return datasets
  156. }
  157. var graphData = window.graphData = getProductDownloadsOverTime()
  158. var datasets = window.datasets = convertToDatasets(graphData)
  159.  
  160. var labels = document.querySelectorAll('#my-payout-list ul.nav-tabs li a')
  161. labels = Array.prototype.map.call(labels, function(e){ return e.textContent })
  162. labels = labels.reverse()
  163.  
  164. console.log('datasets', JSON.stringify(datasets))
  165. console.log('labels', JSON.stringify(labels))
  166.  
  167. var tabContent = document.querySelector('.tab-content')
  168. var graphTabPane = el('<div class="tab-pane fade" id="graphs" />')
  169. var graphCanvas = el('<canvas id="myChart" width="100vw" height="30vh"></canvas>')
  170. graphTabPane.appendChild(graphCanvas)
  171. var warningAlert = tabContent.querySelector('#le-alert')
  172.  
  173. tabContent.insertBefore(graphTabPane, warningAlert)
  174.  
  175. var navTabs = document.querySelector('#my-payout-list ul.nav-tabs')
  176. var graphTab = el('<li><a href="#graphs" data-toggle="tab">Graphs</a></li>')
  177. navTabs.insertBefore(graphTab, navTabs.firstChild)
  178.  
  179. var ctx = document.getElementById("myChart").getContext("2d");
  180. var myChart = window.myChart = new Chart(ctx, {
  181. type: 'line',
  182. data: {
  183. labels: labels,
  184. datasets: datasets,
  185. },
  186. options: {
  187. title: {
  188. display: true,
  189. text: 'Product Downloads Over Time',
  190. },
  191. tooltips: {
  192. mode: 'index',
  193. intersect: false,
  194. itemSort: function (a, b, data) {
  195. return b.yLabel - a.yLabel // descending
  196. }
  197. },
  198. legend: {
  199. onHover: function(e, legendItem) {
  200. if (myChart.hoveringLegendIndex != legendItem.datasetIndex) {
  201. myChart.hoveringLegendIndex = legendItem.datasetIndex
  202. for (var i = 0; i < myChart.data.datasets.length; i++) {
  203. var dataset = myChart.data.datasets[i]
  204. if (i == legendItem.datasetIndex) {
  205. dataset.borderColor = dataset.accentColor
  206. dataset.pointBackgroundColor = dataset.accentColor
  207. } else {
  208. dataset.borderColor = dataset.accentFadedColor
  209. dataset.pointBackgroundColor = dataset.accentFadedColor
  210. }
  211. }
  212. myChart.options.tooltips.enabled = false
  213. myChart.update()
  214. }
  215. }
  216. },
  217. hover: {
  218. mode: 'nearest',
  219. intersect: true,
  220. },
  221. scales: {
  222. yAxes: [{
  223. //type: 'logarithmic',
  224. ticks: {
  225. //stepSize: 5,
  226. //beginAtZero:true,
  227. }
  228. }]
  229. }
  230. }
  231. });
  232.  
  233. myChart.hoveringLegendIndex = -1
  234. myChart.canvas.addEventListener('mousemove', function(e) {
  235. if (myChart.hoveringLegendIndex >= 0) {
  236. if (e.layerX < myChart.legend.left || myChart.legend.right < e.layerX
  237. || e.layerY < myChart.legend.top || myChart.legend.bottom < e.layerY
  238. ) {
  239. myChart.hoveringLegendIndex = -1
  240. for (var i = 0; i < myChart.data.datasets.length; i++) {
  241. var dataset = myChart.data.datasets[i]
  242. dataset.borderColor = dataset.accentColor
  243. dataset.pointBackgroundColor = dataset.accentColor
  244. }
  245. myChart.options.tooltips.enabled = true
  246. myChart.update()
  247. }
  248. }
  249. })