Fossil SCM
/stats_report now uses relative bar lengths, based on (rather arbitrarily) a 500-pixel 100% value.
Commit
3c78bbb0829e58df87604fecf5a8cf70f1d3e4bb
Parent
47ee082a75d4226…
1 file changed
+52
-7
+52
-7
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1864,10 +1864,19 @@ | ||
| 1864 | 1864 | g.zTop, yearPart, zWeek, |
| 1865 | 1865 | nCount, zWeek); |
| 1866 | 1866 | } |
| 1867 | 1867 | db_finalize(&stWeek); |
| 1868 | 1868 | } |
| 1869 | + | |
| 1870 | +/** | |
| 1871 | + Pixel width for the longest bar in | |
| 1872 | + the /stats_report graphs. This is considered | |
| 1873 | + the 100% value and all lengths are calculated | |
| 1874 | + as a percentage of this value. | |
| 1875 | + */ | |
| 1876 | +static int const nStatReportLineWidth = 500; | |
| 1877 | + | |
| 1869 | 1878 | |
| 1870 | 1879 | /* |
| 1871 | 1880 | ** Implements the "byyear" and "bymonth" reports for /stats_report. |
| 1872 | 1881 | ** If includeMonth is true then it generates the "bymonth" report, |
| 1873 | 1882 | ** else the "byyear" report. If zUserName is not NULL and not empty |
| @@ -1890,10 +1899,11 @@ | ||
| 1890 | 1899 | int nEventsPerYear = 0; /* Total even count for the |
| 1891 | 1900 | current year */ |
| 1892 | 1901 | char showYearTotal = 0; /* Flag telling us when to show |
| 1893 | 1902 | the per-year event totals */ |
| 1894 | 1903 | Blob header = empty_blob; /* Page header text */ |
| 1904 | + int nMaxEvents = 1; /* for calculating length of graph bars. */ | |
| 1895 | 1905 | |
| 1896 | 1906 | blob_appendf(&header, "Timeline Events by year%s", |
| 1897 | 1907 | (includeMonth ? "/month" : "")); |
| 1898 | 1908 | blob_appendf(&sql, |
| 1899 | 1909 | "SELECT substr(date(mtime),1,%d) AS timeframe, " |
| @@ -1917,15 +1927,28 @@ | ||
| 1917 | 1927 | @ <th>%s(zTimeLabel)</th> |
| 1918 | 1928 | @ <th>Events</th> |
| 1919 | 1929 | @ <th><!-- relative commits graph --></th> |
| 1920 | 1930 | @ </thead><tbody> |
| 1921 | 1931 | blob_reset(&header); |
| 1932 | + /* | |
| 1933 | + Run the query twice. The first time we calculate the maximum | |
| 1934 | + number of events for a given row. Maybe someone with better SQL | |
| 1935 | + Fu can re-implement this with a single query. | |
| 1936 | + */ | |
| 1937 | + while( SQLITE_ROW == db_step(&query) ){ | |
| 1938 | + int const nCount = db_column_int(&query, 1); | |
| 1939 | + if(nCount>nMaxEvents){ | |
| 1940 | + nMaxEvents = nCount; | |
| 1941 | + } | |
| 1942 | + } | |
| 1943 | + db_reset(&query); | |
| 1922 | 1944 | while( SQLITE_ROW == db_step(&query) ){ |
| 1923 | 1945 | char const * zTimeframe = db_column_text(&query, 0); |
| 1924 | 1946 | int const nCount = db_column_int(&query, 1); |
| 1925 | - int const nSize = 1 + ((nPixelsPerEvent * nCount) | |
| 1926 | - / (includeMonth ? 1 : 10)); | |
| 1947 | + int const nSize = nCount | |
| 1948 | + ? (int)(1.0 * nCount / nMaxEvents * nStatReportLineWidth) | |
| 1949 | + : 1; | |
| 1927 | 1950 | showYearTotal = 0; |
| 1928 | 1951 | if(includeMonth){ |
| 1929 | 1952 | /* For Month/year view, add a separator for each distinct year. */ |
| 1930 | 1953 | if(!*zPrevYear || |
| 1931 | 1954 | (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){ |
| @@ -2021,10 +2044,12 @@ | ||
| 2021 | 2044 | int nRowNumber = 0; /* current TR number */ |
| 2022 | 2045 | int nEventTotal = 0; /* Total event count */ |
| 2023 | 2046 | int rowClass = 0; /* counter for alternating |
| 2024 | 2047 | row colors */ |
| 2025 | 2048 | Blob sql = empty_blob; /* SQL */ |
| 2049 | + int nMaxEvents = 1; /* max number of events for | |
| 2050 | + all rows. */ | |
| 2026 | 2051 | blob_append(&sql, |
| 2027 | 2052 | "SELECT user, " |
| 2028 | 2053 | "COUNT(*) AS eventCount " |
| 2029 | 2054 | "FROM event " |
| 2030 | 2055 | "GROUP BY user ORDER BY eventCount DESC", |
| @@ -2037,15 +2062,24 @@ | ||
| 2037 | 2062 | @ <thead><tr> |
| 2038 | 2063 | @ <th>User</th> |
| 2039 | 2064 | @ <th>Events</th> |
| 2040 | 2065 | @ <th><!-- relative commits graph --></th> |
| 2041 | 2066 | @ </tr></thead><tbody> |
| 2067 | + while( SQLITE_ROW == db_step(&query) ){ | |
| 2068 | + int const nCount = db_column_int(&query, 1); | |
| 2069 | + if(nCount>nMaxEvents){ | |
| 2070 | + nMaxEvents = nCount; | |
| 2071 | + } | |
| 2072 | + } | |
| 2073 | + db_reset(&query); | |
| 2042 | 2074 | while( SQLITE_ROW == db_step(&query) ){ |
| 2043 | 2075 | char const * zUser = db_column_text(&query, 0); |
| 2044 | 2076 | int const nCount = db_column_int(&query, 1); |
| 2045 | - int const nSize = 1+((nPixelsPerEvent * nCount) / 10); | |
| 2046 | - if(!nCount) continue /* arguable! */; | |
| 2077 | + int const nSize = nCount | |
| 2078 | + ? (int)(1.0 * nCount / nMaxEvents * nStatReportLineWidth) | |
| 2079 | + : 0; | |
| 2080 | + if(!nCount) continue /* arguable! Possible? */; | |
| 2047 | 2081 | rowClass = ++nRowNumber % 2; |
| 2048 | 2082 | nEventTotal += nCount; |
| 2049 | 2083 | @<tr class='row%d(rowClass)'> |
| 2050 | 2084 | @ <td> |
| 2051 | 2085 | @ <a href="?view=bymonth&user=%h(zUser)" target="_new">%h(zUser)</a> |
| @@ -2076,12 +2110,14 @@ | ||
| 2076 | 2110 | int nYear = zYear ? strlen(zYear) : 0; |
| 2077 | 2111 | int i = 0; |
| 2078 | 2112 | Stmt qYears = empty_Stmt; |
| 2079 | 2113 | char * zDefaultYear = NULL; |
| 2080 | 2114 | Blob sql = empty_blob; |
| 2081 | - cgi_printf("Select year: "); | |
| 2115 | + int nMaxEvents = 1; /* max number of events for | |
| 2116 | + all rows. */ | |
| 2082 | 2117 | |
| 2118 | + cgi_printf("Select year: "); | |
| 2083 | 2119 | blob_append(&sql, |
| 2084 | 2120 | "SELECT DISTINCT substr(date(mtime),1,4) AS y " |
| 2085 | 2121 | "FROM event WHERE 1 ", -1); |
| 2086 | 2122 | if(zUserName&&*zUserName){ |
| 2087 | 2123 | blob_appendf(&sql,"AND user=%Q ", zUserName); |
| @@ -2138,14 +2174,23 @@ | ||
| 2138 | 2174 | "<th><!-- relative commits graph --></th>" |
| 2139 | 2175 | "</tr></thead>" |
| 2140 | 2176 | "<tbody>"); |
| 2141 | 2177 | db_prepare(&stWeek, blob_str(&sql)); |
| 2142 | 2178 | blob_reset(&sql); |
| 2179 | + while( SQLITE_ROW == db_step(&stWeek) ){ | |
| 2180 | + int const nCount = db_column_int(&stWeek, 1); | |
| 2181 | + if(nCount>nMaxEvents){ | |
| 2182 | + nMaxEvents = nCount; | |
| 2183 | + } | |
| 2184 | + } | |
| 2185 | + db_reset(&stWeek); | |
| 2143 | 2186 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 2144 | 2187 | char const * zWeek = db_column_text(&stWeek,0); |
| 2145 | 2188 | int const nCount = db_column_int(&stWeek,1); |
| 2146 | - int const graphSize = nPixelsPerEvent * nCount; | |
| 2189 | + int const nSize = nCount | |
| 2190 | + ? (int)(1.0 * nCount / nMaxEvents * nStatReportLineWidth) | |
| 2191 | + : 0; | |
| 2147 | 2192 | total += nCount; |
| 2148 | 2193 | cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 2149 | 2194 | cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d", |
| 2150 | 2195 | g.zTop, zYear, zWeek, nCount); |
| 2151 | 2196 | if(zUserName && *zUserName){ |
| @@ -2156,11 +2201,11 @@ | ||
| 2156 | 2201 | cgi_printf("<td>%d</td>",nCount); |
| 2157 | 2202 | cgi_printf("<td>"); |
| 2158 | 2203 | if(nCount){ |
| 2159 | 2204 | cgi_printf("<div class='statistics-report-graph-line'" |
| 2160 | 2205 | "style='height:16px;width:%dpx;'></div>", |
| 2161 | - graphSize); | |
| 2206 | + nSize); | |
| 2162 | 2207 | } |
| 2163 | 2208 | cgi_printf("</td></tr>"); |
| 2164 | 2209 | } |
| 2165 | 2210 | db_finalize(&stWeek); |
| 2166 | 2211 | free(zDefaultYear); |
| 2167 | 2212 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1864,10 +1864,19 @@ | |
| 1864 | g.zTop, yearPart, zWeek, |
| 1865 | nCount, zWeek); |
| 1866 | } |
| 1867 | db_finalize(&stWeek); |
| 1868 | } |
| 1869 | |
| 1870 | /* |
| 1871 | ** Implements the "byyear" and "bymonth" reports for /stats_report. |
| 1872 | ** If includeMonth is true then it generates the "bymonth" report, |
| 1873 | ** else the "byyear" report. If zUserName is not NULL and not empty |
| @@ -1890,10 +1899,11 @@ | |
| 1890 | int nEventsPerYear = 0; /* Total even count for the |
| 1891 | current year */ |
| 1892 | char showYearTotal = 0; /* Flag telling us when to show |
| 1893 | the per-year event totals */ |
| 1894 | Blob header = empty_blob; /* Page header text */ |
| 1895 | |
| 1896 | blob_appendf(&header, "Timeline Events by year%s", |
| 1897 | (includeMonth ? "/month" : "")); |
| 1898 | blob_appendf(&sql, |
| 1899 | "SELECT substr(date(mtime),1,%d) AS timeframe, " |
| @@ -1917,15 +1927,28 @@ | |
| 1917 | @ <th>%s(zTimeLabel)</th> |
| 1918 | @ <th>Events</th> |
| 1919 | @ <th><!-- relative commits graph --></th> |
| 1920 | @ </thead><tbody> |
| 1921 | blob_reset(&header); |
| 1922 | while( SQLITE_ROW == db_step(&query) ){ |
| 1923 | char const * zTimeframe = db_column_text(&query, 0); |
| 1924 | int const nCount = db_column_int(&query, 1); |
| 1925 | int const nSize = 1 + ((nPixelsPerEvent * nCount) |
| 1926 | / (includeMonth ? 1 : 10)); |
| 1927 | showYearTotal = 0; |
| 1928 | if(includeMonth){ |
| 1929 | /* For Month/year view, add a separator for each distinct year. */ |
| 1930 | if(!*zPrevYear || |
| 1931 | (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){ |
| @@ -2021,10 +2044,12 @@ | |
| 2021 | int nRowNumber = 0; /* current TR number */ |
| 2022 | int nEventTotal = 0; /* Total event count */ |
| 2023 | int rowClass = 0; /* counter for alternating |
| 2024 | row colors */ |
| 2025 | Blob sql = empty_blob; /* SQL */ |
| 2026 | blob_append(&sql, |
| 2027 | "SELECT user, " |
| 2028 | "COUNT(*) AS eventCount " |
| 2029 | "FROM event " |
| 2030 | "GROUP BY user ORDER BY eventCount DESC", |
| @@ -2037,15 +2062,24 @@ | |
| 2037 | @ <thead><tr> |
| 2038 | @ <th>User</th> |
| 2039 | @ <th>Events</th> |
| 2040 | @ <th><!-- relative commits graph --></th> |
| 2041 | @ </tr></thead><tbody> |
| 2042 | while( SQLITE_ROW == db_step(&query) ){ |
| 2043 | char const * zUser = db_column_text(&query, 0); |
| 2044 | int const nCount = db_column_int(&query, 1); |
| 2045 | int const nSize = 1+((nPixelsPerEvent * nCount) / 10); |
| 2046 | if(!nCount) continue /* arguable! */; |
| 2047 | rowClass = ++nRowNumber % 2; |
| 2048 | nEventTotal += nCount; |
| 2049 | @<tr class='row%d(rowClass)'> |
| 2050 | @ <td> |
| 2051 | @ <a href="?view=bymonth&user=%h(zUser)" target="_new">%h(zUser)</a> |
| @@ -2076,12 +2110,14 @@ | |
| 2076 | int nYear = zYear ? strlen(zYear) : 0; |
| 2077 | int i = 0; |
| 2078 | Stmt qYears = empty_Stmt; |
| 2079 | char * zDefaultYear = NULL; |
| 2080 | Blob sql = empty_blob; |
| 2081 | cgi_printf("Select year: "); |
| 2082 | |
| 2083 | blob_append(&sql, |
| 2084 | "SELECT DISTINCT substr(date(mtime),1,4) AS y " |
| 2085 | "FROM event WHERE 1 ", -1); |
| 2086 | if(zUserName&&*zUserName){ |
| 2087 | blob_appendf(&sql,"AND user=%Q ", zUserName); |
| @@ -2138,14 +2174,23 @@ | |
| 2138 | "<th><!-- relative commits graph --></th>" |
| 2139 | "</tr></thead>" |
| 2140 | "<tbody>"); |
| 2141 | db_prepare(&stWeek, blob_str(&sql)); |
| 2142 | blob_reset(&sql); |
| 2143 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 2144 | char const * zWeek = db_column_text(&stWeek,0); |
| 2145 | int const nCount = db_column_int(&stWeek,1); |
| 2146 | int const graphSize = nPixelsPerEvent * nCount; |
| 2147 | total += nCount; |
| 2148 | cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 2149 | cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d", |
| 2150 | g.zTop, zYear, zWeek, nCount); |
| 2151 | if(zUserName && *zUserName){ |
| @@ -2156,11 +2201,11 @@ | |
| 2156 | cgi_printf("<td>%d</td>",nCount); |
| 2157 | cgi_printf("<td>"); |
| 2158 | if(nCount){ |
| 2159 | cgi_printf("<div class='statistics-report-graph-line'" |
| 2160 | "style='height:16px;width:%dpx;'></div>", |
| 2161 | graphSize); |
| 2162 | } |
| 2163 | cgi_printf("</td></tr>"); |
| 2164 | } |
| 2165 | db_finalize(&stWeek); |
| 2166 | free(zDefaultYear); |
| 2167 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1864,10 +1864,19 @@ | |
| 1864 | g.zTop, yearPart, zWeek, |
| 1865 | nCount, zWeek); |
| 1866 | } |
| 1867 | db_finalize(&stWeek); |
| 1868 | } |
| 1869 | |
| 1870 | /** |
| 1871 | Pixel width for the longest bar in |
| 1872 | the /stats_report graphs. This is considered |
| 1873 | the 100% value and all lengths are calculated |
| 1874 | as a percentage of this value. |
| 1875 | */ |
| 1876 | static int const nStatReportLineWidth = 500; |
| 1877 | |
| 1878 | |
| 1879 | /* |
| 1880 | ** Implements the "byyear" and "bymonth" reports for /stats_report. |
| 1881 | ** If includeMonth is true then it generates the "bymonth" report, |
| 1882 | ** else the "byyear" report. If zUserName is not NULL and not empty |
| @@ -1890,10 +1899,11 @@ | |
| 1899 | int nEventsPerYear = 0; /* Total even count for the |
| 1900 | current year */ |
| 1901 | char showYearTotal = 0; /* Flag telling us when to show |
| 1902 | the per-year event totals */ |
| 1903 | Blob header = empty_blob; /* Page header text */ |
| 1904 | int nMaxEvents = 1; /* for calculating length of graph bars. */ |
| 1905 | |
| 1906 | blob_appendf(&header, "Timeline Events by year%s", |
| 1907 | (includeMonth ? "/month" : "")); |
| 1908 | blob_appendf(&sql, |
| 1909 | "SELECT substr(date(mtime),1,%d) AS timeframe, " |
| @@ -1917,15 +1927,28 @@ | |
| 1927 | @ <th>%s(zTimeLabel)</th> |
| 1928 | @ <th>Events</th> |
| 1929 | @ <th><!-- relative commits graph --></th> |
| 1930 | @ </thead><tbody> |
| 1931 | blob_reset(&header); |
| 1932 | /* |
| 1933 | Run the query twice. The first time we calculate the maximum |
| 1934 | number of events for a given row. Maybe someone with better SQL |
| 1935 | Fu can re-implement this with a single query. |
| 1936 | */ |
| 1937 | while( SQLITE_ROW == db_step(&query) ){ |
| 1938 | int const nCount = db_column_int(&query, 1); |
| 1939 | if(nCount>nMaxEvents){ |
| 1940 | nMaxEvents = nCount; |
| 1941 | } |
| 1942 | } |
| 1943 | db_reset(&query); |
| 1944 | while( SQLITE_ROW == db_step(&query) ){ |
| 1945 | char const * zTimeframe = db_column_text(&query, 0); |
| 1946 | int const nCount = db_column_int(&query, 1); |
| 1947 | int const nSize = nCount |
| 1948 | ? (int)(1.0 * nCount / nMaxEvents * nStatReportLineWidth) |
| 1949 | : 1; |
| 1950 | showYearTotal = 0; |
| 1951 | if(includeMonth){ |
| 1952 | /* For Month/year view, add a separator for each distinct year. */ |
| 1953 | if(!*zPrevYear || |
| 1954 | (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){ |
| @@ -2021,10 +2044,12 @@ | |
| 2044 | int nRowNumber = 0; /* current TR number */ |
| 2045 | int nEventTotal = 0; /* Total event count */ |
| 2046 | int rowClass = 0; /* counter for alternating |
| 2047 | row colors */ |
| 2048 | Blob sql = empty_blob; /* SQL */ |
| 2049 | int nMaxEvents = 1; /* max number of events for |
| 2050 | all rows. */ |
| 2051 | blob_append(&sql, |
| 2052 | "SELECT user, " |
| 2053 | "COUNT(*) AS eventCount " |
| 2054 | "FROM event " |
| 2055 | "GROUP BY user ORDER BY eventCount DESC", |
| @@ -2037,15 +2062,24 @@ | |
| 2062 | @ <thead><tr> |
| 2063 | @ <th>User</th> |
| 2064 | @ <th>Events</th> |
| 2065 | @ <th><!-- relative commits graph --></th> |
| 2066 | @ </tr></thead><tbody> |
| 2067 | while( SQLITE_ROW == db_step(&query) ){ |
| 2068 | int const nCount = db_column_int(&query, 1); |
| 2069 | if(nCount>nMaxEvents){ |
| 2070 | nMaxEvents = nCount; |
| 2071 | } |
| 2072 | } |
| 2073 | db_reset(&query); |
| 2074 | while( SQLITE_ROW == db_step(&query) ){ |
| 2075 | char const * zUser = db_column_text(&query, 0); |
| 2076 | int const nCount = db_column_int(&query, 1); |
| 2077 | int const nSize = nCount |
| 2078 | ? (int)(1.0 * nCount / nMaxEvents * nStatReportLineWidth) |
| 2079 | : 0; |
| 2080 | if(!nCount) continue /* arguable! Possible? */; |
| 2081 | rowClass = ++nRowNumber % 2; |
| 2082 | nEventTotal += nCount; |
| 2083 | @<tr class='row%d(rowClass)'> |
| 2084 | @ <td> |
| 2085 | @ <a href="?view=bymonth&user=%h(zUser)" target="_new">%h(zUser)</a> |
| @@ -2076,12 +2110,14 @@ | |
| 2110 | int nYear = zYear ? strlen(zYear) : 0; |
| 2111 | int i = 0; |
| 2112 | Stmt qYears = empty_Stmt; |
| 2113 | char * zDefaultYear = NULL; |
| 2114 | Blob sql = empty_blob; |
| 2115 | int nMaxEvents = 1; /* max number of events for |
| 2116 | all rows. */ |
| 2117 | |
| 2118 | cgi_printf("Select year: "); |
| 2119 | blob_append(&sql, |
| 2120 | "SELECT DISTINCT substr(date(mtime),1,4) AS y " |
| 2121 | "FROM event WHERE 1 ", -1); |
| 2122 | if(zUserName&&*zUserName){ |
| 2123 | blob_appendf(&sql,"AND user=%Q ", zUserName); |
| @@ -2138,14 +2174,23 @@ | |
| 2174 | "<th><!-- relative commits graph --></th>" |
| 2175 | "</tr></thead>" |
| 2176 | "<tbody>"); |
| 2177 | db_prepare(&stWeek, blob_str(&sql)); |
| 2178 | blob_reset(&sql); |
| 2179 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 2180 | int const nCount = db_column_int(&stWeek, 1); |
| 2181 | if(nCount>nMaxEvents){ |
| 2182 | nMaxEvents = nCount; |
| 2183 | } |
| 2184 | } |
| 2185 | db_reset(&stWeek); |
| 2186 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 2187 | char const * zWeek = db_column_text(&stWeek,0); |
| 2188 | int const nCount = db_column_int(&stWeek,1); |
| 2189 | int const nSize = nCount |
| 2190 | ? (int)(1.0 * nCount / nMaxEvents * nStatReportLineWidth) |
| 2191 | : 0; |
| 2192 | total += nCount; |
| 2193 | cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 2194 | cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d", |
| 2195 | g.zTop, zYear, zWeek, nCount); |
| 2196 | if(zUserName && *zUserName){ |
| @@ -2156,11 +2201,11 @@ | |
| 2201 | cgi_printf("<td>%d</td>",nCount); |
| 2202 | cgi_printf("<td>"); |
| 2203 | if(nCount){ |
| 2204 | cgi_printf("<div class='statistics-report-graph-line'" |
| 2205 | "style='height:16px;width:%dpx;'></div>", |
| 2206 | nSize); |
| 2207 | } |
| 2208 | cgi_printf("</td></tr>"); |
| 2209 | } |
| 2210 | db_finalize(&stWeek); |
| 2211 | free(zDefaultYear); |
| 2212 |