Просмотр исходного кода

Add repeated transactions

Add flot resize library
Update to more recent flot git repo
Closes #5
master
Chris Smith 13 лет назад
Родитель
Сommit
0f78f8a3b0
4 измененных файлов: 107 добавлений и 4 удалений
  1. 1
    1
      .gitmodules
  2. 87
    0
      analyser.js
  3. 1
    1
      externals/flot
  4. 18
    2
      index.html

+ 1
- 1
.gitmodules Просмотреть файл

1
 [submodule "externals/flot"]
1
 [submodule "externals/flot"]
2
 	path = externals/flot
2
 	path = externals/flot
3
-	url = https://github.com/FooBarWidget/flot.git
3
+	url = https://github.com/tback/flot.git 
4
 [submodule "externals/jquery.history"]
4
 [submodule "externals/jquery.history"]
5
 	path = externals/jquery.history
5
 	path = externals/jquery.history
6
 	url = https://github.com/tkyk/jquery-history-plugin.git
6
 	url = https://github.com/tkyk/jquery-history-plugin.git

+ 87
- 0
analyser.js Просмотреть файл

188
  return this.toFixed(2).replace(/([0-9])(?=([0-9]{3})+\.)/g, '$1,');
188
  return this.toFixed(2).replace(/([0-9])(?=([0-9]{3})+\.)/g, '$1,');
189
 };
189
 };
190
 
190
 
191
+/**
192
+ * Computes the arithmatic mean, variance and deviation for the given array.
193
+ *
194
+ * @param a Array of numbers to be averaged
195
+ * @return A map containing the mean, variance and deviation
196
+ */
197
+function getAverage(a){
198
+ var r = {mean: 0, variance: 0, deviation: 0};
199
+ var length = a.length;
200
+
201
+ // Sum the array
202
+ for (var sum = 0, i = length; i--; sum += a[i]);
203
+
204
+ var mean = r.mean = sum / length
205
+
206
+ // Sum the squares of the differences from the mean
207
+ for (var i = length, sum = 0; i--; sum += Math.pow(a[i] - mean, 2));
208
+
209
+ r.deviation = Math.sqrt(r.variance = sum / length)
210
+ return r;
211
+}
212
+
191
 /**
213
 /**
192
  * Adds an 'alt' class to every other visible row in the specified table.
214
  * Adds an 'alt' class to every other visible row in the specified table.
193
  *
215
  *
309
  });
331
  });
310
 }
332
 }
311
 
333
 
334
+/**
335
+ * Calculates repeat transactions within the specified data.
336
+ *
337
+ * @param data The data to be analysed
338
+ */
339
+function calculateRepeatTransactions(data) {
340
+ $('#repeats').show();
341
+ $('#repeats tr.data').remove();
342
+ var table = $('#repeats table');
343
+
344
+ var descs = {};
345
+
346
+ $.each(data, function() {
347
+  if (!descs[this.Description]) { descs[this.Description] = []; }
348
+  descs[this.Description].push(this);
349
+ });
350
+
351
+ var monthTotal = 0;
352
+ $.each(descs, function(desc) {
353
+  // We only care if there are at least more than 2
354
+  if (this.length < 3) { return; }
355
+
356
+  var lastTime = 0;
357
+  var differences = [];
358
+  var amounts = [];
359
+
360
+  $.each(this, function() {
361
+   var time = new Date(this.Date.date).getTime();
362
+   lastTime > 0 && differences.push(time - lastTime);
363
+   lastTime = time;
364
+   amounts.push(this.Amount);
365
+  });
366
+
367
+  var average = getAverage(differences);
368
+  var averageAmount = getAverage(amounts);
369
+
370
+  // I may have just made this metric up. Sue me.
371
+  var stability = average.deviation / average.mean;
372
+  var periodInDays = average.mean / (1000 * 60 * 60 * 24);
373
+
374
+  if (stability < 0.5) {
375
+   // Seems quite reliable...
376
+   if ((periodInDays >= 5 && periodInDays <= 9) || (periodInDays >= 27 && periodInDays <= 32)) {
377
+    // Roughly weekly or monthly
378
+    var monthValue = (periodInDays <= 9 ? 4 : 1) * averageAmount.mean;
379
+
380
+    var tr = $('<tr class="data"/>').appendTo(table);
381
+    $('<td/>').text(desc).appendTo(tr);
382
+    $('<td/>').text(this[0].Category ? this[0].Category : 'Unsorted').appendTo(tr);
383
+    $('<td/>').text(periodInDays <= 9 ? 'Weekly' : 'Monthly').appendTo(tr);
384
+    $('<td class="amount"/>').text(averageAmount.mean.toCurrency()).appendTo(tr);
385
+    $('<td class="amount"/>').text(monthValue.toCurrency()).appendTo(tr);
386
+
387
+    monthTotal += monthValue;
388
+   }
389
+  }
390
+ });
391
+
392
+ colourTableRows(table);
393
+ var tr = $('<tr/>').addClass('data total').appendTo(table);
394
+ $('<th colspan="4" class="total">Total</th>').appendTo(tr);
395
+ $('<td class="amount"></td>').text(monthTotal.toCurrency()).appendTo(tr);
396
+}
397
+
312
 /**
398
 /**
313
  * Displays transactions and draws a category pie chart for the specified
399
  * Displays transactions and draws a category pie chart for the specified
314
  * date range. Note that dates have a granularity of a month.
400
  * date range. Note that dates have a granularity of a month.
385
 
471
 
386
  colourTableRows(table);
472
  colourTableRows(table);
387
  drawCategoryPieChart(included, incoming);
473
  drawCategoryPieChart(included, incoming);
474
+ calculateRepeatTransactions(included);
388
 }
475
 }
389
 
476
 
390
 $(function() {
477
 $(function() {

+ 1
- 1
externals/flot

1
-Subproject commit 171538ec32e26a6167d8e43b9722ec2bf612115b
1
+Subproject commit 6328221ea9d507b2150e59f09d9eb9265e9dc127

+ 18
- 2
index.html Просмотреть файл

5
   <script src="externals/flot/jquery.js" type="text/javascript"></script>
5
   <script src="externals/flot/jquery.js" type="text/javascript"></script>
6
   <script src="externals/flot/jquery.flot.js" type="text/javascript"></script>
6
   <script src="externals/flot/jquery.flot.js" type="text/javascript"></script>
7
   <script src="externals/flot/jquery.flot.pie.js" type="text/javascript"></script>
7
   <script src="externals/flot/jquery.flot.pie.js" type="text/javascript"></script>
8
+  <script src="externals/flot/jquery.flot.resize.js" type="text/javascript"></script>
8
   <script src="externals/flot/jquery.flot.selection.js" type="text/javascript"></script>
9
   <script src="externals/flot/jquery.flot.selection.js" type="text/javascript"></script>
9
   <script src="externals/flot/jquery.flot.stack.js" type="text/javascript"></script>
10
   <script src="externals/flot/jquery.flot.stack.js" type="text/javascript"></script>
10
   <script src="externals/jquery.history/jquery.history.js" type="text/javascript"></script>
11
   <script src="externals/jquery.history/jquery.history.js" type="text/javascript"></script>
28
    #historytable tr.collapsed { opacity: 0.6; }
29
    #historytable tr.collapsed { opacity: 0.6; }
29
    table tr.total td, table tr.total th { background-color: #666; color: #fff; }
30
    table tr.total td, table tr.total th { background-color: #666; color: #fff; }
30
    .amount { text-align: right; }
31
    .amount { text-align: right; }
32
+   .datatable { width: 100%; }
31
   </style>
33
   </style>
32
  </head>
34
  </head>
33
  <body>
35
  <body>
39
   <div class="left">
41
   <div class="left">
40
    <h2>Transaction History</h2>
42
    <h2>Transaction History</h2>
41
    <div id="history" style="width: 100%; height: 300px;" class="graph"></div>
43
    <div id="history" style="width: 100%; height: 300px;" class="graph"></div>
42
-   <div id="historytable" style="display: none;"><h3>Transactions for ??</h3><table><tr><th>Date</th><th>Type</th><th>Category</th><th>Description</th><th>Amount</th></tr></table></div>
44
+   <div id="historytable" style="display: none;">
45
+    <h3>Transactions for ??</h3>
46
+    <table class="datatable"><tr><th>Date</th><th>Type</th><th>Category</th><th>Description</th><th>Amount</th></tr></table>
47
+   </div>
43
   </div>
48
   </div>
44
   <div class="right">
49
   <div class="right">
45
    <h2>Categories</h2>
50
    <h2>Categories</h2>
46
    <div id="expense" style="width: 100%; height: 300px;" class="graph"></div>
51
    <div id="expense" style="width: 100%; height: 300px;" class="graph"></div>
47
    <h2>Expense Categories</h2>
52
    <h2>Expense Categories</h2>
48
-   <div id="cathistory" style="width: 100%; height: 600px;" class="graph"></div>
53
+   <!-- The tick labels on the X-Axis extend a bit beyond the edge of the
54
+        graph, so make the graph 50px smaller so the page doesn't scroll -->
55
+   <div style="padding-right: 50px;">
56
+    <div id="cathistory" style="width: 100%; height: 600px;" class="graph"></div>
57
+   </div>
58
+   <div id="repeats" style="display: none;">
59
+    <h2>Repeat Transactions</h2>
60
+    <table class="datatable">
61
+     <tr><th rowspan="2">Transaction</th><th rowspan="2">Category</th><th rowspan="2">Frequency</th><th colspan="2">Average amount</th></tr>
62
+     <tr><th>Per trans</th><th>Per month</th></tr>
63
+    </table>
64
+   </div>
49
   </div>
65
   </div>
50
  </body>
66
  </body>
51
 </html>
67
 </html>

Загрузка…
Отмена
Сохранить