We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
fix histogram on printing page
The user histogram is broken on ocf.io/stats/printing. The culprit is https://github.com/ocf/ocfweb/blob/ed143b8f1c59e58157780007fe5fd104ee18d944/ocfweb/stats/printing.py#L58
We should use `SEMESTERLY_QUOTA + 5` instead of 105.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ocfweb/stats/printing.py`
Content:
```
1 import time
2 from collections import defaultdict
3 from datetime import date
4 from datetime import timedelta
5 from functools import partial
6 
7 from django.http import HttpResponse
8 from django.shortcuts import render
9 from matplotlib.figure import Figure
10 from ocflib.lab import stats
11 from ocflib.printing.printers import PRINTERS
12 from ocflib.printing.quota import get_connection
13 from ocflib.printing.quota import SEMESTERLY_QUOTA
14 
15 from ocfweb.caching import periodic
16 from ocfweb.component.graph import plot_to_image_bytes
17 
18 
19 ALL_PRINTERS = ('papercut', 'pagefault', 'logjam', 'logjam-old', 'deforestation')
20 ACTIVE_PRINTERS = ('papercut', 'pagefault', 'logjam')
21 
22 
23 def stats_printing(request):
24     return render(
25         request,
26         'stats/printing.html',
27         {
28             'title': 'Printing Statistics',
29             'current_printers': PRINTERS,
30             'toner_changes': _toner_changes(),
31             'last_month': [
32                 date.today() - timedelta(days=i)
33                 for i in range(30)
34             ],
35             'pages_per_day': _pages_per_day(),
36         },
37     )
38 
39 
40 def semester_histogram(request):
41     return HttpResponse(
42         plot_to_image_bytes(_semester_histogram(), format='svg'),
43         content_type='image/svg+xml',
44     )
45 
46 
47 @periodic(300)
48 def _semester_histogram():
49     with get_connection() as c:
50         c.execute(
51             'SELECT `user`, `semester` FROM `printed` WHERE `semester` > 0',
52         )
53         users = [SEMESTERLY_QUOTA - int(r['semester']) for r in c]
54 
55     fig = Figure(figsize=(10, 5))
56     ax = fig.add_subplot(1, 1, 1)
57     ax.locator_params(nbins=20)
58     ax.hist(users, bins=list(range(0, 105, 5)))
59     ax.grid(True)
60     ax.set_xlim(SEMESTERLY_QUOTA, 0)
61     ax.set_ylabel('Number of users')
62     ax.set_xlabel('Remaining balance')
63     ax.set_title('Remaining balances this semester')
64 
65     return fig
66 
67 
68 @periodic(3600)
69 def _toner_changes():
70     return [
71         (
72             printer,
73             _toner_used_by_printer(printer),
74         )
75         for printer in ACTIVE_PRINTERS
76     ]
77 
78 
79 def _toner_used_by_printer(printer, cutoff=.05, since=None):
80     """Returns toner used for a printer since a given date (by default it
81     returns toner used for this semester).
82 
83     Toner numbers can be significantly noisy, including significant diffs
84     whenever toner gets taken out and put back in whenever there is a jam.
85     Because of this it's hard to determine if a new toner is inserted into a
86     printer or if it was the same toner again. To reduce this noise we only
87     count diffs that are smaller than a cutoff which empirically seems to be
88     more accurate.
89     """
90     if not since:
91         since = stats.current_semester_start()
92 
93     with stats.get_connection() as cursor:
94         cursor.execute(
95             '''
96             CREATE TEMPORARY TABLE ordered1
97                 (PRIMARY KEY (position))
98                 AS (
99                     SELECT * FROM (
100                         SELECT
101                             T.*,
102                             @rownum := @rownum + 1 AS position
103                             FROM (
104                                 (
105                                     SELECT * FROM printer_toner_public
106                                     WHERE printer = %s AND
107                                     date > %s
108                                     ORDER BY date
109                                 ) AS T,
110                                 (SELECT @rownum := 0) AS r
111                             )
112                     ) AS x
113                 )
114         ''', (printer, since.strftime('%Y-%m-%d')),
115         )
116         cursor.execute('''
117             CREATE TEMPORARY TABLE ordered2
118                 (PRIMARY KEY (position))
119                 AS (SELECT * FROM ordered1)
120         ''')
121         cursor.execute('''
122             CREATE TEMPORARY TABLE diffs
123             AS (SELECT
124                 B.date AS date,
125                 A.value/A.max - B.value/B.max as pct_diff
126                 FROM
127                     ordered1 as A,
128                     ordered2 as B
129                 WHERE
130                     B.position = A.position + 1)
131         ''')
132         cursor.execute(
133             '''
134             SELECT SUM(pct_diff) as toner_used
135             FROM
136             diffs
137             WHERE
138             ABS(pct_diff)<%s
139         ''', (cutoff,),
140         )
141         result = cursor.fetchone()['toner_used']
142         return float(result or 0.0)
143 
144 
145 @periodic(120)
146 def _pages_per_day():
147     with stats.get_connection() as cursor:
148         cursor.execute('''
149             SELECT max(value) as value, cast(date as date) as date, printer
150                 FROM printer_pages_public
151                 GROUP BY cast(date as date), printer
152                 ORDER BY date ASC, printer ASC
153         ''')
154 
155         # Resolves the issue of possible missing dates.
156         # defaultdict(lambda: defaultdict(int)) doesn't work due to inability to pickle local objects like lambdas;
157         # this effectively does the same thing as that.
158         pages_printed = defaultdict(partial(defaultdict, int))
159         last_seen = {}
160 
161         for row in cursor:
162             if row['printer'] in last_seen:
163                 pages_printed.setdefault(row['date'], defaultdict(int))
164                 pages_printed[row['date']][row['printer']] = (
165                     row['value'] - last_seen[row['printer']]
166                 )
167             last_seen[row['printer']] = row['value']
168 
169     return pages_printed
170 
171 
172 def _pages_printed_for_printer(printer, resolution=100):
173     with stats.get_connection() as cursor:
174         cursor.execute(
175             '''
176             SELECT Z.date, Z.value FROM (
177                 SELECT
178                     T.*,
179                     @rownum := @rownum + 1 AS position
180                 FROM (
181                     (
182                         SELECT * FROM printer_pages_public
183                         WHERE printer = %s
184                         ORDER BY date
185                     ) AS T,
186                     (SELECT @rownum := 0) AS r
187                 )
188             ) as Z
189             WHERE Z.position mod %s = 0
190         ''', (printer, resolution),
191         )
192         return [
193             (time.mktime(row['date'].timetuple()) * 1000, row['value'])
194             for row in cursor
195         ]
196 
197 
198 @periodic(3600)
199 def _pages_printed_data():
200     return [
201         {
202             'name': printer,
203             'animation': False,
204             'data': _pages_printed_for_printer(printer),
205         }
206         for printer in ALL_PRINTERS
207     ]
208 
209 
210 def pages_printed(request):
211     return render(
212         request,
213         'stats/printing/pages-printed.html',
214         {
215             'title': 'Pages Printed',
216             'data': _pages_printed_data(),
217         },
218     )
219
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ocfweb/stats/printing.py b/ocfweb/stats/printing.py
--- a/ocfweb/stats/printing.py
+++ b/ocfweb/stats/printing.py
@@ -55,7 +55,7 @@
     fig = Figure(figsize=(10, 5))
     ax = fig.add_subplot(1, 1, 1)
     ax.locator_params(nbins=20)
-    ax.hist(users, bins=list(range(0, 105, 5)))
+    ax.hist(users, bins=list(range(0, SEMESTERLY_QUOTA + 5, 5)))
     ax.grid(True)
     ax.set_xlim(SEMESTERLY_QUOTA, 0)
     ax.set_ylabel('Number of users')

{"golden_diff": "diff --git a/ocfweb/stats/printing.py b/ocfweb/stats/printing.py\n--- a/ocfweb/stats/printing.py\n+++ b/ocfweb/stats/printing.py\n@@ -55,7 +55,7 @@\n     fig = Figure(figsize=(10, 5))\n     ax = fig.add_subplot(1, 1, 1)\n     ax.locator_params(nbins=20)\n-    ax.hist(users, bins=list(range(0, 105, 5)))\n+    ax.hist(users, bins=list(range(0, SEMESTERLY_QUOTA + 5, 5)))\n     ax.grid(True)\n     ax.set_xlim(SEMESTERLY_QUOTA, 0)\n     ax.set_ylabel('Number of users')\n", "issue": "fix histogram on printing page\nThe user histogram is broken on ocf.io/stats/printing. The culprit is https://github.com/ocf/ocfweb/blob/ed143b8f1c59e58157780007fe5fd104ee18d944/ocfweb/stats/printing.py#L58\r\nWe should use `SEMESTERLY_QUOTA + 5` instead of 105.\n", "before_files": [{"content": "import time\nfrom collections import defaultdict\nfrom datetime import date\nfrom datetime import timedelta\nfrom functools import partial\n\nfrom django.http import HttpResponse\nfrom django.shortcuts import render\nfrom matplotlib.figure import Figure\nfrom ocflib.lab import stats\nfrom ocflib.printing.printers import PRINTERS\nfrom ocflib.printing.quota import get_connection\nfrom ocflib.printing.quota import SEMESTERLY_QUOTA\n\nfrom ocfweb.caching import periodic\nfrom ocfweb.component.graph import plot_to_image_bytes\n\n\nALL_PRINTERS = ('papercut', 'pagefault', 'logjam', 'logjam-old', 'deforestation')\nACTIVE_PRINTERS = ('papercut', 'pagefault', 'logjam')\n\n\ndef stats_printing(request):\n    return render(\n        request,\n        'stats/printing.html',\n        {\n            'title': 'Printing Statistics',\n            'current_printers': PRINTERS,\n            'toner_changes': _toner_changes(),\n            'last_month': [\n                date.today() - timedelta(days=i)\n                for i in range(30)\n            ],\n            'pages_per_day': _pages_per_day(),\n        },\n    )\n\n\ndef semester_histogram(request):\n    return HttpResponse(\n        plot_to_image_bytes(_semester_histogram(), format='svg'),\n        content_type='image/svg+xml',\n    )\n\n\n@periodic(300)\ndef _semester_histogram():\n    with get_connection() as c:\n        c.execute(\n            'SELECT `user`, `semester` FROM `printed` WHERE `semester` > 0',\n        )\n        users = [SEMESTERLY_QUOTA - int(r['semester']) for r in c]\n\n    fig = Figure(figsize=(10, 5))\n    ax = fig.add_subplot(1, 1, 1)\n    ax.locator_params(nbins=20)\n    ax.hist(users, bins=list(range(0, 105, 5)))\n    ax.grid(True)\n    ax.set_xlim(SEMESTERLY_QUOTA, 0)\n    ax.set_ylabel('Number of users')\n    ax.set_xlabel('Remaining balance')\n    ax.set_title('Remaining balances this semester')\n\n    return fig\n\n\n@periodic(3600)\ndef _toner_changes():\n    return [\n        (\n            printer,\n            _toner_used_by_printer(printer),\n        )\n        for printer in ACTIVE_PRINTERS\n    ]\n\n\ndef _toner_used_by_printer(printer, cutoff=.05, since=None):\n    \"\"\"Returns toner used for a printer since a given date (by default it\n    returns toner used for this semester).\n\n    Toner numbers can be significantly noisy, including significant diffs\n    whenever toner gets taken out and put back in whenever there is a jam.\n    Because of this it's hard to determine if a new toner is inserted into a\n    printer or if it was the same toner again. To reduce this noise we only\n    count diffs that are smaller than a cutoff which empirically seems to be\n    more accurate.\n    \"\"\"\n    if not since:\n        since = stats.current_semester_start()\n\n    with stats.get_connection() as cursor:\n        cursor.execute(\n            '''\n            CREATE TEMPORARY TABLE ordered1\n                (PRIMARY KEY (position))\n                AS (\n                    SELECT * FROM (\n                        SELECT\n                            T.*,\n                            @rownum := @rownum + 1 AS position\n                            FROM (\n                                (\n                                    SELECT * FROM printer_toner_public\n                                    WHERE printer = %s AND\n                                    date > %s\n                                    ORDER BY date\n                                ) AS T,\n                                (SELECT @rownum := 0) AS r\n                            )\n                    ) AS x\n                )\n        ''', (printer, since.strftime('%Y-%m-%d')),\n        )\n        cursor.execute('''\n            CREATE TEMPORARY TABLE ordered2\n                (PRIMARY KEY (position))\n                AS (SELECT * FROM ordered1)\n        ''')\n        cursor.execute('''\n            CREATE TEMPORARY TABLE diffs\n            AS (SELECT\n                B.date AS date,\n                A.value/A.max - B.value/B.max as pct_diff\n                FROM\n                    ordered1 as A,\n                    ordered2 as B\n                WHERE\n                    B.position = A.position + 1)\n        ''')\n        cursor.execute(\n            '''\n            SELECT SUM(pct_diff) as toner_used\n            FROM\n            diffs\n            WHERE\n            ABS(pct_diff)<%s\n        ''', (cutoff,),\n        )\n        result = cursor.fetchone()['toner_used']\n        return float(result or 0.0)\n\n\n@periodic(120)\ndef _pages_per_day():\n    with stats.get_connection() as cursor:\n        cursor.execute('''\n            SELECT max(value) as value, cast(date as date) as date, printer\n                FROM printer_pages_public\n                GROUP BY cast(date as date), printer\n                ORDER BY date ASC, printer ASC\n        ''')\n\n        # Resolves the issue of possible missing dates.\n        # defaultdict(lambda: defaultdict(int)) doesn't work due to inability to pickle local objects like lambdas;\n        # this effectively does the same thing as that.\n        pages_printed = defaultdict(partial(defaultdict, int))\n        last_seen = {}\n\n        for row in cursor:\n            if row['printer'] in last_seen:\n                pages_printed.setdefault(row['date'], defaultdict(int))\n                pages_printed[row['date']][row['printer']] = (\n                    row['value'] - last_seen[row['printer']]\n                )\n            last_seen[row['printer']] = row['value']\n\n    return pages_printed\n\n\ndef _pages_printed_for_printer(printer, resolution=100):\n    with stats.get_connection() as cursor:\n        cursor.execute(\n            '''\n            SELECT Z.date, Z.value FROM (\n                SELECT\n                    T.*,\n                    @rownum := @rownum + 1 AS position\n                FROM (\n                    (\n                        SELECT * FROM printer_pages_public\n                        WHERE printer = %s\n                        ORDER BY date\n                    ) AS T,\n                    (SELECT @rownum := 0) AS r\n                )\n            ) as Z\n            WHERE Z.position mod %s = 0\n        ''', (printer, resolution),\n        )\n        return [\n            (time.mktime(row['date'].timetuple()) * 1000, row['value'])\n            for row in cursor\n        ]\n\n\n@periodic(3600)\ndef _pages_printed_data():\n    return [\n        {\n            'name': printer,\n            'animation': False,\n            'data': _pages_printed_for_printer(printer),\n        }\n        for printer in ALL_PRINTERS\n    ]\n\n\ndef pages_printed(request):\n    return render(\n        request,\n        'stats/printing/pages-printed.html',\n        {\n            'title': 'Pages Printed',\n            'data': _pages_printed_data(),\n        },\n    )\n", "path": "ocfweb/stats/printing.py"}], "after_files": [{"content": "import time\nfrom collections import defaultdict\nfrom datetime import date\nfrom datetime import timedelta\nfrom functools import partial\n\nfrom django.http import HttpResponse\nfrom django.shortcuts import render\nfrom matplotlib.figure import Figure\nfrom ocflib.lab import stats\nfrom ocflib.printing.printers import PRINTERS\nfrom ocflib.printing.quota import get_connection\nfrom ocflib.printing.quota import SEMESTERLY_QUOTA\n\nfrom ocfweb.caching import periodic\nfrom ocfweb.component.graph import plot_to_image_bytes\n\n\nALL_PRINTERS = ('papercut', 'pagefault', 'logjam', 'logjam-old', 'deforestation')\nACTIVE_PRINTERS = ('papercut', 'pagefault', 'logjam')\n\n\ndef stats_printing(request):\n    return render(\n        request,\n        'stats/printing.html',\n        {\n            'title': 'Printing Statistics',\n            'current_printers': PRINTERS,\n            'toner_changes': _toner_changes(),\n            'last_month': [\n                date.today() - timedelta(days=i)\n                for i in range(30)\n            ],\n            'pages_per_day': _pages_per_day(),\n        },\n    )\n\n\ndef semester_histogram(request):\n    return HttpResponse(\n        plot_to_image_bytes(_semester_histogram(), format='svg'),\n        content_type='image/svg+xml',\n    )\n\n\n@periodic(300)\ndef _semester_histogram():\n    with get_connection() as c:\n        c.execute(\n            'SELECT `user`, `semester` FROM `printed` WHERE `semester` > 0',\n        )\n        users = [SEMESTERLY_QUOTA - int(r['semester']) for r in c]\n\n    fig = Figure(figsize=(10, 5))\n    ax = fig.add_subplot(1, 1, 1)\n    ax.locator_params(nbins=20)\n    ax.hist(users, bins=list(range(0, SEMESTERLY_QUOTA + 5, 5)))\n    ax.grid(True)\n    ax.set_xlim(SEMESTERLY_QUOTA, 0)\n    ax.set_ylabel('Number of users')\n    ax.set_xlabel('Remaining balance')\n    ax.set_title('Remaining balances this semester')\n\n    return fig\n\n\n@periodic(3600)\ndef _toner_changes():\n    return [\n        (\n            printer,\n            _toner_used_by_printer(printer),\n        )\n        for printer in ACTIVE_PRINTERS\n    ]\n\n\ndef _toner_used_by_printer(printer, cutoff=.05, since=None):\n    \"\"\"Returns toner used for a printer since a given date (by default it\n    returns toner used for this semester).\n\n    Toner numbers can be significantly noisy, including significant diffs\n    whenever toner gets taken out and put back in whenever there is a jam.\n    Because of this it's hard to determine if a new toner is inserted into a\n    printer or if it was the same toner again. To reduce this noise we only\n    count diffs that are smaller than a cutoff which empirically seems to be\n    more accurate.\n    \"\"\"\n    if not since:\n        since = stats.current_semester_start()\n\n    with stats.get_connection() as cursor:\n        cursor.execute(\n            '''\n            CREATE TEMPORARY TABLE ordered1\n                (PRIMARY KEY (position))\n                AS (\n                    SELECT * FROM (\n                        SELECT\n                            T.*,\n                            @rownum := @rownum + 1 AS position\n                            FROM (\n                                (\n                                    SELECT * FROM printer_toner_public\n                                    WHERE printer = %s AND\n                                    date > %s\n                                    ORDER BY date\n                                ) AS T,\n                                (SELECT @rownum := 0) AS r\n                            )\n                    ) AS x\n                )\n        ''', (printer, since.strftime('%Y-%m-%d')),\n        )\n        cursor.execute('''\n            CREATE TEMPORARY TABLE ordered2\n                (PRIMARY KEY (position))\n                AS (SELECT * FROM ordered1)\n        ''')\n        cursor.execute('''\n            CREATE TEMPORARY TABLE diffs\n            AS (SELECT\n                B.date AS date,\n                A.value/A.max - B.value/B.max as pct_diff\n                FROM\n                    ordered1 as A,\n                    ordered2 as B\n                WHERE\n                    B.position = A.position + 1)\n        ''')\n        cursor.execute(\n            '''\n            SELECT SUM(pct_diff) as toner_used\n            FROM\n            diffs\n            WHERE\n            ABS(pct_diff)<%s\n        ''', (cutoff,),\n        )\n        result = cursor.fetchone()['toner_used']\n        return float(result or 0.0)\n\n\n@periodic(120)\ndef _pages_per_day():\n    with stats.get_connection() as cursor:\n        cursor.execute('''\n            SELECT max(value) as value, cast(date as date) as date, printer\n                FROM printer_pages_public\n                GROUP BY cast(date as date), printer\n                ORDER BY date ASC, printer ASC\n        ''')\n\n        # Resolves the issue of possible missing dates.\n        # defaultdict(lambda: defaultdict(int)) doesn't work due to inability to pickle local objects like lambdas;\n        # this effectively does the same thing as that.\n        pages_printed = defaultdict(partial(defaultdict, int))\n        last_seen = {}\n\n        for row in cursor:\n            if row['printer'] in last_seen:\n                pages_printed.setdefault(row['date'], defaultdict(int))\n                pages_printed[row['date']][row['printer']] = (\n                    row['value'] - last_seen[row['printer']]\n                )\n            last_seen[row['printer']] = row['value']\n\n    return pages_printed\n\n\ndef _pages_printed_for_printer(printer, resolution=100):\n    with stats.get_connection() as cursor:\n        cursor.execute(\n            '''\n            SELECT Z.date, Z.value FROM (\n                SELECT\n                    T.*,\n                    @rownum := @rownum + 1 AS position\n                FROM (\n                    (\n                        SELECT * FROM printer_pages_public\n                        WHERE printer = %s\n                        ORDER BY date\n                    ) AS T,\n                    (SELECT @rownum := 0) AS r\n                )\n            ) as Z\n            WHERE Z.position mod %s = 0\n        ''', (printer, resolution),\n        )\n        return [\n            (time.mktime(row['date'].timetuple()) * 1000, row['value'])\n            for row in cursor\n        ]\n\n\n@periodic(3600)\ndef _pages_printed_data():\n    return [\n        {\n            'name': printer,\n            'animation': False,\n            'data': _pages_printed_for_printer(printer),\n        }\n        for printer in ALL_PRINTERS\n    ]\n\n\ndef pages_printed(request):\n    return render(\n        request,\n        'stats/printing/pages-printed.html',\n        {\n            'title': 'Pages Printed',\n            'data': _pages_printed_data(),\n        },\n    )\n", "path": "ocfweb/stats/printing.py"}]}