| | @@ -166,11 +166,11 @@ |
| 166 | 166 | case 'e': |
| 167 | 167 | return "technotes"; |
| 168 | 168 | case 'f': |
| 169 | 169 | return "forum posts"; |
| 170 | 170 | case 'h': |
| 171 | | - return "forum threads"; |
| 171 | + return "new forum threads"; |
| 172 | 172 | case 'w': |
| 173 | 173 | return "wiki changes"; |
| 174 | 174 | case 't': |
| 175 | 175 | return "ticket changes"; |
| 176 | 176 | case 'g': |
| | @@ -671,99 +671,254 @@ |
| 671 | 671 | ** |
| 672 | 672 | ** If zUserName is not NULL then the report is restricted to events |
| 673 | 673 | ** created by the named user account. |
| 674 | 674 | */ |
| 675 | 675 | static void stats_report_year_weeks(const char *zUserName){ |
| 676 | | - const char *zYear = P("y"); /* Year for which report shown */ |
| 676 | + const char *zYear = P("y"); /* Year for which report shown */ |
| 677 | + int bShowAll = PB("sa"); /* Show all weeks if true, active if false */ |
| 678 | + char *zLimit; /* Date of last week to show */ |
| 679 | + Stmt q; |
| 680 | + int nMaxEvents = 1; /* max number of events for all rows. */ |
| 681 | + int rowCount = 0; |
| 682 | + int total; |
| 683 | + int iCurrentWeek; /* Current week number */ |
| 684 | + double rNowFraction = 0.0; /* Fraction of current week that has |
| 685 | + ** passed */ |
| 686 | + |
| 687 | + stats_report_init_view(); |
| 688 | + style_submenu_sql("y", "Year:", |
| 689 | + "WITH RECURSIVE a(b) AS (" |
| 690 | + " SELECT substr(date('now'),1,4) UNION ALL" |
| 691 | + " SELECT b-1 FROM a\n" |
| 692 | + " WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)" |
| 693 | + ") SELECT b, b FROM a ORDER BY b DESC" |
| 694 | + ); |
| 695 | + style_submenu_checkbox("sa", "Show-All", 0, 0); |
| 696 | + if( zYear==0 || strlen(zYear)!=4 ){ |
| 697 | + zYear = db_text("1970","SELECT substr(date('now'),1,4);"); |
| 698 | + } |
| 699 | + zLimit = db_text("1971-01-01", |
| 700 | + "SELECT min(date('%q-01-01','+1 year','-1 day'),date())", |
| 701 | + zYear |
| 702 | + ); |
| 703 | + db_multi_exec( |
| 704 | + "CREATE TEMP TABLE wkdata(wk,n);\n" |
| 705 | + "WITH RECURSIVE c(wkn) AS (\n" |
| 706 | + " VALUES(0)\n" |
| 707 | + " UNION ALL\n" |
| 708 | + " SELECT wkn+1 FROM c\n" |
| 709 | + " WHERE date('%q-01-01',format('%%+d days',wkn*7+7))<=%Q\n" |
| 710 | + ")\n" |
| 711 | + "INSERT INTO wkdata(wk,n)\n" |
| 712 | + " SELECT c.wkn, coalesce(x.n,0)\n" |
| 713 | + " FROM c LEFT JOIN (\n" |
| 714 | + " SELECT 0+strftime('%%W',mtime) AS w,\n" |
| 715 | + " count(*) AS n \n" |
| 716 | + " FROM v_reports\n" |
| 717 | + " WHERE mtime BETWEEN julianday('%q-01-01 00:00:00')\n" |
| 718 | + " AND julianday(%Q)\n" |
| 719 | + " AND ifnull(coalesce(euser,user,'')=%Q,1)\n" |
| 720 | + " GROUP BY w) AS x ON c.wkn=x.w;\n", |
| 721 | + zYear, zLimit, |
| 722 | + zYear, zLimit, zUserName |
| 723 | + ); |
| 724 | + cgi_printf("<br>\n"); |
| 725 | + @ <h1>Timeline events (%h(stats_report_label_for_type())) |
| 726 | + @ for the calendar weeks of %h(zYear) |
| 727 | + if( zUserName ){ |
| 728 | + @ for user %h(zUserName) |
| 729 | + } |
| 730 | + @ </h1> |
| 731 | + iCurrentWeek = db_int(0, |
| 732 | + "SELECT strftime('%%W','now') WHERE date() LIKE '%q-%%'", zYear); |
| 733 | + if( iCurrentWeek>0 ){ |
| 734 | + rNowFraction = db_double(0.5, |
| 735 | + "SELECT (unixepoch()-unixepoch('now','weekday 0','-7 days'))/604800.0;"); |
| 736 | + } |
| 737 | + style_table_sorter(); |
| 738 | + cgi_printf("<table class='statistics-report-table-events sortable' " |
| 739 | + "border='0' cellpadding='2' width='100%%' " |
| 740 | + "cellspacing='0' data-column-types='tnx' data-init-sort='0'>\n"); |
| 741 | + cgi_printf("<thead><tr>" |
| 742 | + "<th>Week</th>" |
| 743 | + "<th>Events</th>" |
| 744 | + "<th width='90%%'><!-- relative commits graph --></th>" |
| 745 | + "</tr></thead>\n" |
| 746 | + "<tbody>\n"); |
| 747 | + nMaxEvents = db_int(0, "SELECT max(n) FROM wkdata"); |
| 748 | + db_prepare(&q, "SELECT wk, n FROM wkdata ORDER BY wk DESC"); |
| 749 | + while( SQLITE_ROW == db_step(&q) ){ |
| 750 | + const int iWeek = db_column_int(&q,0); |
| 751 | + const int nCount = db_column_int(&q,1); |
| 752 | + int nSize = (nCount>0 && nMaxEvents>0) |
| 753 | + ? (int)(100 * nCount / nMaxEvents) |
| 754 | + : 0; |
| 755 | + if( nCount==0 && !bShowAll ) continue; |
| 756 | + if(!nSize) nSize = 1; |
| 757 | + cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 758 | + cgi_printf("<td><a href='%R/timeline?yw=%t%02d&y=%s", |
| 759 | + zYear, iWeek, |
| 760 | + statsReportTimelineYFlag); |
| 761 | + if( zUserName ){ |
| 762 | + cgi_printf("&u=%t",zUserName); |
| 763 | + } |
| 764 | + cgi_printf("'>%02d</a></td>",iWeek); |
| 765 | + |
| 766 | + cgi_printf("<td>%d</td>",nCount); |
| 767 | + cgi_printf("<td style='white-space: nowrap;'>"); |
| 768 | + if( nCount ){ |
| 769 | + if( iCurrentWeek==iWeek |
| 770 | + && rNowFraction>0.05 |
| 771 | + && nMaxEvents>0 |
| 772 | + ){ |
| 773 | + /* If the timespan covered by this row contains "now", then project |
| 774 | + ** the number of changes until the completion of the week and |
| 775 | + ** show a dashed box of that projection. */ |
| 776 | + int nProj = (int)(((double)nCount)/rNowFraction); |
| 777 | + int nExtra = (int)(((double)nCount)/rNowFraction) - nCount; |
| 778 | + int nXSize = (100 * nExtra)/nMaxEvents; |
| 779 | + @ <span class='statistics-report-graph-line' \ |
| 780 | + @ style='display:inline-block;min-width:%d(nSize)%%;'> </span>\ |
| 781 | + @ <span class='statistics-report-graph-extra' title='%d(nProj)' \ |
| 782 | + @ style='display:inline-block;min-width:%d(nXSize)%%;'> </span>\ |
| 783 | + }else{ |
| 784 | + @ <div class='statistics-report-graph-line' \ |
| 785 | + @ style='width:%d(nSize)%%;'> </div> \ |
| 786 | + } |
| 787 | + } |
| 788 | + cgi_printf("</td></tr>\n"); |
| 789 | + } |
| 790 | + db_finalize(&q); |
| 791 | + cgi_printf("</tbody></table>\n<br>\n<div\n"); |
| 792 | + total = db_int(0, "SELECT sum(n) FROM wkdata"); |
| 793 | + cgi_printf("Total events: %d<br>\n", total); |
| 794 | + if( total ){ |
| 795 | + cgi_printf("Weeks covered: %d<br>\n", |
| 796 | + db_int(0, "SELECT count(*) FROM wkdata")); |
| 797 | + cgi_printf("Average events per week: %.1f<br>\n", |
| 798 | + db_double(0.0, "SELECT avg(n) FROM wkdata")); |
| 799 | + cgi_printf("Median events per week: %.1f<br>\n", |
| 800 | + db_double(0.0, "SELECT median(n) FROM wkdata")); |
| 801 | + cgi_printf("Active weeks: %d<br>\n", |
| 802 | + db_int(0, "SELECT count(*) FROM wkdata WHERE n>0")); |
| 803 | + cgi_printf("Average events per active week: %.1f<br>\n", |
| 804 | + db_double(0.0, "SELECT avg(n) FROM wkdata WHERE n>0")); |
| 805 | + cgi_printf("Median events per active week: %.1f<br>\n", |
| 806 | + db_double(0.0, "SELECT median(n) FROM wkdata WHERE n>0")); |
| 807 | + } |
| 808 | +} |
| 809 | + |
| 810 | +/* |
| 811 | +** Generator for the by-day report (RPT_BYDAY). |
| 812 | +** |
| 813 | +** The "y" query parameter is the year in format YYYY. |
| 814 | +** |
| 815 | +** If zUserName is not NULL then the report is restricted to events |
| 816 | +** created by the named user account. |
| 817 | +*/ |
| 818 | +static void stats_report_year_days(const char *zUserName){ |
| 819 | + const char *zYear = P("y"); /* Year for which report shown */ |
| 820 | + int bShowAll = PB("sa"); /* Show all days if true, active if false */ |
| 821 | + char *zLimit; /* Date of last day to show */ |
| 677 | 822 | Stmt q; |
| 678 | | - int nMaxEvents = 1; /* max number of events for |
| 679 | | - all rows. */ |
| 680 | | - int iterations = 0; /* # of active time periods. */ |
| 823 | + int nMaxEvents = 1; /* max number of events for all rows. */ |
| 681 | 824 | int rowCount = 0; |
| 682 | | - int total = 0; |
| 683 | | - char *zCurrentWeek; /* Current week number */ |
| 684 | | - double rNowFraction = 0.0; /* Fraction of current week that has |
| 685 | | - ** passed */ |
| 825 | + int total; |
| 826 | + char *zCurrentDay; /* Current week number */ |
| 827 | + double rNowFraction = 0.0; /* Fraction of current day that has |
| 828 | + ** passed */ |
| 686 | 829 | |
| 687 | 830 | stats_report_init_view(); |
| 688 | 831 | style_submenu_sql("y", "Year:", |
| 689 | 832 | "WITH RECURSIVE a(b) AS (" |
| 690 | 833 | " SELECT substr(date('now'),1,4) UNION ALL" |
| 691 | | - " SELECT b-1 FROM a" |
| 834 | + " SELECT b-1 FROM a\n" |
| 692 | 835 | " WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)" |
| 693 | | - ") SELECT b, b FROM a ORDER BY b DESC"); |
| 836 | + ") SELECT b, b FROM a ORDER BY b DESC" |
| 837 | + ); |
| 838 | + style_submenu_checkbox("sa", "Show-All", 0, 0); |
| 694 | 839 | if( zYear==0 || strlen(zYear)!=4 ){ |
| 695 | 840 | zYear = db_text("1970","SELECT substr(date('now'),1,4);"); |
| 696 | 841 | } |
| 842 | + zLimit = db_text("1971-01-01", |
| 843 | + "SELECT min(date('%q-01-01','+1 year','-1 day'),date())", |
| 844 | + zYear |
| 845 | + ); |
| 846 | + db_multi_exec( |
| 847 | + "CREATE TEMP TABLE daydata(dn,isodate,dow,n);\n" |
| 848 | + "WITH RECURSIVE c(daynum, isodate, dow) AS (\n" |
| 849 | + " VALUES(0,'%q-01-01',0+strftime('%%w','%q-01-01'))\n" |
| 850 | + " UNION ALL\n" |
| 851 | + " SELECT daynum+1, date(isodate,'+1 day'), (dow+1)%%6\n" |
| 852 | + " FROM c\n" |
| 853 | + " WHERE isodate<%Q\n" |
| 854 | + ")\n" |
| 855 | + "INSERT INTO daydata(dn,isodate,dow,n)\n" |
| 856 | + " SELECT c.daynum, c.isodate, c.dow, coalesce(x.n,0)\n" |
| 857 | + " FROM c LEFT JOIN (\n" |
| 858 | + " SELECT date(mtime) AS edate, count(*) AS n\n" |
| 859 | + " FROM v_reports\n" |
| 860 | + " WHERE mtime BETWEEN julianday('%q-01-01 00:00:00')\n" |
| 861 | + " AND julianday(%Q)\n" |
| 862 | + " AND ifnull(coalesce(euser,user,'')=%Q,1)\n" |
| 863 | + " GROUP BY edate) AS x ON c.isodate=x.edate;\n", |
| 864 | + zYear, zYear, |
| 865 | + zLimit, |
| 866 | + zYear, |
| 867 | + zLimit, |
| 868 | + zUserName |
| 869 | + ); |
| 697 | 870 | cgi_printf("<br>\n"); |
| 698 | | - db_prepare(&q, |
| 699 | | - "SELECT DISTINCT strftime('%%W',mtime) AS wk, " |
| 700 | | - " count(*) AS n " |
| 701 | | - " FROM v_reports " |
| 702 | | - " WHERE %Q=substr(date(mtime),1,4) " |
| 703 | | - " AND mtime < current_timestamp " |
| 704 | | - " AND ifnull(coalesce(euser,user,'')=%Q,1)" |
| 705 | | - " GROUP BY wk ORDER BY wk DESC", zYear, zUserName); |
| 706 | 871 | @ <h1>Timeline events (%h(stats_report_label_for_type())) |
| 707 | 872 | @ for the calendar weeks of %h(zYear) |
| 708 | 873 | if( zUserName ){ |
| 709 | 874 | @ for user %h(zUserName) |
| 710 | 875 | } |
| 711 | 876 | @ </h1> |
| 712 | | - zCurrentWeek = db_text(0, |
| 713 | | - "SELECT strftime('%%W','now') WHERE date() LIKE '%q%%'", |
| 714 | | - zYear); |
| 715 | | - if( zCurrentWeek ){ |
| 877 | + zCurrentDay = db_text(0, "SELECT date()"); |
| 878 | + if( zCurrentDay ){ |
| 716 | 879 | rNowFraction = db_double(0.5, |
| 717 | | - "SELECT (unixepoch()-unixepoch('now','weekday 0','-7 days'))/604800.0;"); |
| 880 | + "SELECT (unixepoch()-unixepoch('now','start of day'))/604800.0;"); |
| 718 | 881 | } |
| 719 | | - style_table_sorter(); |
| 882 | + style_table_sorter(); |
| 720 | 883 | cgi_printf("<table class='statistics-report-table-events sortable' " |
| 721 | 884 | "border='0' cellpadding='2' width='100%%' " |
| 722 | 885 | "cellspacing='0' data-column-types='tnx' data-init-sort='0'>\n"); |
| 723 | 886 | cgi_printf("<thead><tr>" |
| 724 | 887 | "<th>Week</th>" |
| 725 | 888 | "<th>Events</th>" |
| 726 | 889 | "<th width='90%%'><!-- relative commits graph --></th>" |
| 727 | 890 | "</tr></thead>\n" |
| 728 | 891 | "<tbody>\n"); |
| 729 | | - while( SQLITE_ROW == db_step(&q) ){ |
| 730 | | - int nCount = db_column_int(&q, 1); |
| 731 | | - if( zCurrentWeek!=0 |
| 732 | | - && strcmp(db_column_text(&q,0),zCurrentWeek)==0 |
| 733 | | - && rNowFraction>0.05 |
| 734 | | - ){ |
| 735 | | - nCount = (int)(((double)nCount)/rNowFraction); |
| 736 | | - } |
| 737 | | - if(nCount>nMaxEvents){ |
| 738 | | - nMaxEvents = nCount; |
| 739 | | - } |
| 740 | | - ++iterations; |
| 741 | | - } |
| 742 | | - db_reset(&q); |
| 743 | | - while( SQLITE_ROW == db_step(&q) ){ |
| 744 | | - const char *zWeek = db_column_text(&q,0); |
| 745 | | - const int nCount = db_column_int(&q,1); |
| 892 | + nMaxEvents = db_int(0, "SELECT max(n) FROM daydata"); |
| 893 | + db_prepare(&q, "SELECT isodate,dow,n FROM daydata ORDER BY dn DESC"); |
| 894 | + while( SQLITE_ROW == db_step(&q) ){ |
| 895 | + static const char *azDayName[] = { |
| 896 | + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" |
| 897 | + }; |
| 898 | + const char *zDate = db_column_text(&q,0); |
| 899 | + int iDOW = db_column_int(&q,1); |
| 900 | + const int nCount = db_column_int(&q,2); |
| 746 | 901 | int nSize = (nCount>0 && nMaxEvents>0) |
| 747 | 902 | ? (int)(100 * nCount / nMaxEvents) |
| 748 | 903 | : 0; |
| 904 | + assert( iDOW>=0 && iDOW<=6 ); |
| 905 | + if( nCount==0 && !bShowAll ) continue; |
| 749 | 906 | if(!nSize) nSize = 1; |
| 750 | | - total += nCount; |
| 751 | 907 | cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 752 | | - cgi_printf("<td><a href='%R/timeline?yw=%t%s&y=%s", |
| 753 | | - zYear, zWeek, |
| 754 | | - statsReportTimelineYFlag); |
| 908 | + cgi_printf("<td><a href='%R/timeline?ymd=%s&y=%s", |
| 909 | + zDate, statsReportTimelineYFlag); |
| 755 | 910 | if( zUserName ){ |
| 756 | 911 | cgi_printf("&u=%t",zUserName); |
| 757 | 912 | } |
| 758 | | - cgi_printf("'>%s</a></td>",zWeek); |
| 913 | + cgi_printf("'>%s (%s)</a></td>",zDate,azDayName[iDOW]); |
| 759 | 914 | |
| 760 | 915 | cgi_printf("<td>%d</td>",nCount); |
| 761 | 916 | cgi_printf("<td style='white-space: nowrap;'>"); |
| 762 | 917 | if( nCount ){ |
| 763 | | - if( zCurrentWeek!=0 |
| 764 | | - && strcmp(zWeek, zCurrentWeek)==0 |
| 918 | + if( zCurrentDay!=0 |
| 919 | + && strcmp(zDate, zCurrentDay)==0 |
| 765 | 920 | && rNowFraction>0.05 |
| 766 | 921 | && nMaxEvents>0 |
| 767 | 922 | ){ |
| 768 | 923 | /* If the timespan covered by this row contains "now", then project |
| 769 | 924 | ** the number of changes until the completion of the week and |
| | @@ -781,115 +936,26 @@ |
| 781 | 936 | } |
| 782 | 937 | } |
| 783 | 938 | cgi_printf("</td></tr>\n"); |
| 784 | 939 | } |
| 785 | 940 | db_finalize(&q); |
| 786 | | - cgi_printf("</tbody></table>"); |
| 787 | | - if(total){ |
| 788 | | - int nAvg = iterations ? (total/iterations) : 0; |
| 789 | | - cgi_printf("<br><div>Total events: %d<br>" |
| 790 | | - "Average per active week: %d</div>", |
| 791 | | - total, nAvg); |
| 792 | | - } |
| 793 | | -} |
| 794 | | - |
| 795 | | -/* |
| 796 | | -** Generator for the by-day report (RPT_BYDAY). |
| 797 | | -** |
| 798 | | -** The "y" query parameter is the year in format YYYY. |
| 799 | | -** |
| 800 | | -** If zUserName is not NULL then the report is restricted to events |
| 801 | | -** created by the named user account. |
| 802 | | -*/ |
| 803 | | -static void stats_report_year_days(const char *zUserName){ |
| 804 | | - const char *zYear = P("y"); /* Year for which report shown */ |
| 805 | | - Stmt q; |
| 806 | | - int nMaxEvents = 1; /* max number of events for |
| 807 | | - all rows. */ |
| 808 | | - int iterations = 0; /* # of active time periods. */ |
| 809 | | - int rowCount = 0; |
| 810 | | - int total = 0; |
| 811 | | - |
| 812 | | - stats_report_init_view(); |
| 813 | | - style_submenu_sql("y", "Year:", |
| 814 | | - "WITH RECURSIVE a(b) AS (" |
| 815 | | - " SELECT substr(date('now'),1,4) UNION ALL" |
| 816 | | - " SELECT b-1 FROM a" |
| 817 | | - " WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)" |
| 818 | | - ") SELECT b, b FROM a ORDER BY b DESC"); |
| 819 | | - if( zYear==0 || strlen(zYear)!=4 ){ |
| 820 | | - zYear = db_text("1970","SELECT substr(date('now'),1,4);"); |
| 821 | | - } |
| 822 | | - cgi_printf("<br>\n"); |
| 823 | | - db_prepare(&q, |
| 824 | | - "SELECT DISTINCT strftime('%%w',mtime) AS wkday, " |
| 825 | | - " date(mtime) AS date," |
| 826 | | - " count(*) AS n " |
| 827 | | - " FROM v_reports" |
| 828 | | - " WHERE %Q=substr(date(mtime),1,4) " |
| 829 | | - " AND mtime < current_timestamp " |
| 830 | | - " AND ifnull(coalesce(euser,user,'')=%Q,1)" |
| 831 | | - " GROUP BY date ORDER BY date DESC", zYear, zUserName); |
| 832 | | - @ <h1>Timeline events (%h(stats_report_label_for_type())) |
| 833 | | - @ for each day of %h(zYear) |
| 834 | | - if( zUserName ){ |
| 835 | | - @ for user %h(zUserName) |
| 836 | | - } |
| 837 | | - @ </h1> |
| 838 | | - style_table_sorter(); |
| 839 | | - cgi_printf("<table class='statistics-report-table-events sortable' " |
| 840 | | - "border='0' cellpadding='2' width='100%%' " |
| 841 | | - "cellspacing='0' data-column-types='tnx' data-init-sort='0'>\n"); |
| 842 | | - cgi_printf("<thead><tr>" |
| 843 | | - "<th>Date</th>" |
| 844 | | - "<th>Events</th>" |
| 845 | | - "<th width='90%%'><!-- relative commits graph --></th>" |
| 846 | | - "</tr></thead>\n" |
| 847 | | - "<tbody>\n"); |
| 848 | | - while( SQLITE_ROW == db_step(&q) ){ |
| 849 | | - int nCount = db_column_int(&q, 2); |
| 850 | | - if(nCount>nMaxEvents){ |
| 851 | | - nMaxEvents = nCount; |
| 852 | | - } |
| 853 | | - ++iterations; |
| 854 | | - } |
| 855 | | - db_reset(&q); |
| 856 | | - while( SQLITE_ROW == db_step(&q) ){ |
| 857 | | - static const char *azDayName[] = { |
| 858 | | - "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" |
| 859 | | - }; |
| 860 | | - int dayOfWeek = db_column_int(&q,0); |
| 861 | | - const char *zDate = db_column_text(&q,1); |
| 862 | | - const int nCount = db_column_int(&q,2); |
| 863 | | - int nSize = (nCount>0 && nMaxEvents>0) |
| 864 | | - ? (int)(100 * nCount / nMaxEvents) |
| 865 | | - : 0; |
| 866 | | - if(!nSize) nSize = 1; |
| 867 | | - total += nCount; |
| 868 | | - cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 869 | | - cgi_printf("<td><a href='%R/timeline?ymd=%s&y=%s", |
| 870 | | - zDate, statsReportTimelineYFlag); |
| 871 | | - if( zUserName ){ |
| 872 | | - cgi_printf("&u=%t",zUserName); |
| 873 | | - } |
| 874 | | - cgi_printf("'>%s (%s)</a></td>",zDate, azDayName[dayOfWeek]); |
| 875 | | - |
| 876 | | - cgi_printf("<td>%d</td>",nCount); |
| 877 | | - cgi_printf("<td style='white-space: nowrap;'>"); |
| 878 | | - if( nCount ){ |
| 879 | | - @ <div class='statistics-report-graph-line' \ |
| 880 | | - @ style='width:%d(nSize)%%;'> </div> \ |
| 881 | | - } |
| 882 | | - cgi_printf("</td></tr>\n"); |
| 883 | | - } |
| 884 | | - db_finalize(&q); |
| 885 | | - cgi_printf("</tbody></table>"); |
| 886 | | - if(total){ |
| 887 | | - int nAvg = iterations ? (total/iterations) : 0; |
| 888 | | - cgi_printf("<br><div>Total events: %d<br>" |
| 889 | | - "Average per active day: %d</div>", |
| 890 | | - total, nAvg); |
| 941 | + cgi_printf("</tbody></table>\n<br>\n<div\n"); |
| 942 | + total = db_int(0, "SELECT sum(n) FROM daydata"); |
| 943 | + cgi_printf("Total events: %d<br>\n", total); |
| 944 | + if( total ){ |
| 945 | + cgi_printf("Days covered: %d<br>\n", |
| 946 | + db_int(0, "SELECT count(*) FROM daydata")); |
| 947 | + cgi_printf("Average events per day: %.1f<br>\n", |
| 948 | + db_double(0.0, "SELECT avg(n) FROM daydata")); |
| 949 | + cgi_printf("Median events per day: %.1f<br>\n", |
| 950 | + db_double(0.0, "SELECT median(n) FROM daydata")); |
| 951 | + cgi_printf("Active days: %d<br>\n", |
| 952 | + db_int(0, "SELECT count(*) FROM daydata WHERE n>0")); |
| 953 | + cgi_printf("Average events per active day: %.1f<br>\n", |
| 954 | + db_double(0.0, "SELECT avg(n) FROM daydata WHERE n>0")); |
| 955 | + cgi_printf("Median events per active day: %.1f<br>\n", |
| 956 | + db_double(0.0, "SELECT median(n) FROM daydata WHERE n>0")); |
| 891 | 957 | } |
| 892 | 958 | } |
| 893 | 959 | |
| 894 | 960 | |
| 895 | 961 | /* |
| 896 | 962 | |