{"action":"created","comment":{"url":"https://api.github.com/repos/fsr-itse/EvaP/pulls/comments/28957890","id":28957890,"diff_hunk":"@@ -13,54 +13,59 @@ class ExcelExporter(object):\n \n     def __init__(self, semester):\n         self.semester = semester\n-\n-    styles = {\n-        'default':       xlwt.Style.default_style,\n-        'avg':           xlwt.easyxf('alignment: horiz centre; font: bold on; borders: left medium, top medium, bottom medium'),\n-        'variance_low':  xlwt.easyxf('alignment: horiz centre; borders: right medium', num_format_str=\"0.0\"),\n-        'variance_med':  xlwt.easyxf('pattern: pattern solid, fore_colour gray25; alignment: horiz centre; borders: right medium', num_format_str=\"0.0\"),\n-        'variance_high': xlwt.easyxf('pattern: pattern solid, fore_colour gray40; alignment: horiz centre; borders: right medium', num_format_str=\"0.0\"),\n-        'headline':      xlwt.easyxf('font: bold on, height 400; alignment: horiz centre, vert centre, wrap on', num_format_str=\"0.0\"),\n-        'course':        xlwt.easyxf('alignment: horiz centre, wrap on, rota 90; borders: left medium, top medium'),\n-        'course_unfinished': xlwt.easyxf('alignment: horiz centre, wrap on, rota 90; borders: left medium, top medium; font: italic on'),\n-        'total_voters': xlwt.easyxf('alignment: horiz centre; borders: left medium, bottom medium, right medium'),\n-        'bold':          xlwt.easyxf('font: bold on'),\n-        'border_left':   xlwt.easyxf('borders: left medium'),\n-        'border_right':  xlwt.easyxf('borders: right medium'),\n-        'border_top_bottom_right': xlwt.easyxf('borders: top medium, bottom medium, right medium')}\n-\n-    # We only assign different colors every 0.2 grades, because excel limits the number of custom colors\n-    # colors up to 0x20 are already pre-defined in the xls-format\n-    grades_and_indices = [(1 + i*2/10.0, 0x20 + i) for i in range(21)]\n-\n-    grade_base_style = 'pattern: pattern solid, fore_colour {}; alignment: horiz centre; font: bold on; borders: left medium'\n-    # Adding evaP colors to palette\n-    for grade, index in grades_and_indices:\n-        color_name = 'custom_grade_color_' + str(grade)\n-        style_name = 'grade_' + str(grade)\n-        xlwt.add_palette_colour(color_name, index)\n-        styles[style_name] = xlwt.easyxf(grade_base_style.format(color_name), num_format_str=\"0.0\")\n-\n-    @classmethod\n-    def add_color_palette_to_workbook(cls, workbook):\n-        for grade, index in cls.grades_and_indices:\n-            workbook.set_colour_RGB(index, *get_grade_color(grade))\n-\n-    @staticmethod\n-    def grade_to_style(grade):\n-        # Round grade to .2 steps\n-        grade = int(grade * 5) / 5\n-        return 'grade_' + str(grade)\n-\n-    @staticmethod\n-    def variance_to_style(variance):\n-        rounded_variance = round(variance, 1)\n-        if rounded_variance < 0.5:\n-            return 'variance_low'\n-        elif rounded_variance < 1.0:\n-            return 'variance_med'\n-        else:\n-            return 'variance_high'\n+        self.styles = dict()\n+\n+    def normalize_number(self, number):\n+        \"\"\" floors 'number' to a multiply of self.STEP \"\"\"\n+        return round(int(number / self.STEP + 0.0001) * self.STEP, 1)\n+\n+    def create_style(self, workbook, base_style, style_name, palette_index, color):\n+        color_name = style_name + \"_color\"\n+        xlwt.add_palette_colour(color_name, palette_index)\n+        workbook.set_colour_RGB(palette_index, *color)\n+        self.styles[style_name] = xlwt.easyxf(base_style.format(color_name), num_format_str=\"0.0\")\n+\n+    def init_styles(self, workbook):\n+        self.styles = {\n+            'default':       xlwt.Style.default_style,\n+            'avg':           xlwt.easyxf('alignment: horiz centre; font: bold on; borders: left medium, top medium, bottom medium'),\n+            'headline':      xlwt.easyxf('font: bold on, height 400; alignment: horiz centre, vert centre, wrap on', num_format_str=\"0.0\"),\n+            'course':        xlwt.easyxf('alignment: horiz centre, wrap on, rota 90; borders: left medium, top medium'),\n+            'course_unfinished': xlwt.easyxf('alignment: horiz centre, wrap on, rota 90; borders: left medium, top medium; font: italic on'),\n+            'total_voters': xlwt.easyxf('alignment: horiz centre; borders: left medium, bottom medium, right medium'),\n+            'bold':          xlwt.easyxf('font: bold on'),\n+            'border_left':   xlwt.easyxf('borders: left medium'),\n+            'border_right':  xlwt.easyxf('borders: right medium'),\n+            'border_top_bottom_right': xlwt.easyxf('borders: top medium, bottom medium, right medium')}\n+\n+        CUSTOM_COLOR_START = 8\n+        NUM_GRADE_COLORS = 21 # 1.0 to 5.0 in 0.2 steps\n+        NUM_DEVIATION_COLORS = 30 # about to change in next commit\n+        self.STEP = 0.2 # we only have a limited number of custom colors\n+        self.STEP_INVERSE = (0.2) # we only have a limited number of custom colors","path":"evap/results/exporters.py","position":88,"original_position":88,"commit_id":"02a1b4613c0f614de0c435330c2b9347ca508169","original_commit_id":"02a1b4613c0f614de0c435330c2b9347ca508169","user":{"login":"janno42","id":1781719,"avatar_url":"https://avatars.githubusercontent.com/u/1781719?v=3","gravatar_id":"","url":"https://api.github.com/users/janno42","html_url":"https://github.com/janno42","followers_url":"https://api.github.com/users/janno42/followers","following_url":"https://api.github.com/users/janno42/following{/other_user}","gists_url":"https://api.github.com/users/janno42/gists{/gist_id}","starred_url":"https://api.github.com/users/janno42/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/janno42/subscriptions","organizations_url":"https://api.github.com/users/janno42/orgs","repos_url":"https://api.github.com/users/janno42/repos","events_url":"https://api.github.com/users/janno42/events{/privacy}","received_events_url":"https://api.github.com/users/janno42/received_events","type":"User","site_admin":false},"body":"do we need that?","created_at":"2015-04-23T12:36:13Z","updated_at":"2015-04-23T12:36:13Z","html_url":"https://github.com/fsr-itse/EvaP/pull/573#discussion_r28957890","pull_request_url":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573","_links":{"self":{"href":"https://api.github.com/repos/fsr-itse/EvaP/pulls/comments/28957890"},"html":{"href":"https://github.com/fsr-itse/EvaP/pull/573#discussion_r28957890"},"pull_request":{"href":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573"}}},"pull_request":{"url":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573","id":33936337,"html_url":"https://github.com/fsr-itse/EvaP/pull/573","diff_url":"https://github.com/fsr-itse/EvaP/pull/573.diff","patch_url":"https://github.com/fsr-itse/EvaP/pull/573.patch","issue_url":"https://api.github.com/repos/fsr-itse/EvaP/issues/573","number":573,"state":"open","locked":false,"title":"Replace all median grades and variances by standard deviation","user":{"login":"karyon","id":1891915,"avatar_url":"https://avatars.githubusercontent.com/u/1891915?v=3","gravatar_id":"","url":"https://api.github.com/users/karyon","html_url":"https://github.com/karyon","followers_url":"https://api.github.com/users/karyon/followers","following_url":"https://api.github.com/users/karyon/following{/other_user}","gists_url":"https://api.github.com/users/karyon/gists{/gist_id}","starred_url":"https://api.github.com/users/karyon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karyon/subscriptions","organizations_url":"https://api.github.com/users/karyon/orgs","repos_url":"https://api.github.com/users/karyon/repos","events_url":"https://api.github.com/users/karyon/events{/privacy}","received_events_url":"https://api.github.com/users/karyon/received_events","type":"User","site_admin":false},"body":"this PR replaces #570, and still fixes #558.\r\n\r\nit also replaces all median grades and variances by the standard deviation.","created_at":"2015-04-23T09:05:21Z","updated_at":"2015-04-23T12:36:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"81a9a159a1b3aa8eb151fbead383177f85bc62b9","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573/commits","review_comments_url":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573/comments","review_comment_url":"https://api.github.com/repos/fsr-itse/EvaP/pulls/comments{/number}","comments_url":"https://api.github.com/repos/fsr-itse/EvaP/issues/573/comments","statuses_url":"https://api.github.com/repos/fsr-itse/EvaP/statuses/02a1b4613c0f614de0c435330c2b9347ca508169","head":{"label":"karyon:introduce_deviation","ref":"introduce_deviation","sha":"02a1b4613c0f614de0c435330c2b9347ca508169","user":{"login":"karyon","id":1891915,"avatar_url":"https://avatars.githubusercontent.com/u/1891915?v=3","gravatar_id":"","url":"https://api.github.com/users/karyon","html_url":"https://github.com/karyon","followers_url":"https://api.github.com/users/karyon/followers","following_url":"https://api.github.com/users/karyon/following{/other_user}","gists_url":"https://api.github.com/users/karyon/gists{/gist_id}","starred_url":"https://api.github.com/users/karyon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karyon/subscriptions","organizations_url":"https://api.github.com/users/karyon/orgs","repos_url":"https://api.github.com/users/karyon/repos","events_url":"https://api.github.com/users/karyon/events{/privacy}","received_events_url":"https://api.github.com/users/karyon/received_events","type":"User","site_admin":false},"repo":{"id":20780224,"name":"EvaP","full_name":"karyon/EvaP","owner":{"login":"karyon","id":1891915,"avatar_url":"https://avatars.githubusercontent.com/u/1891915?v=3","gravatar_id":"","url":"https://api.github.com/users/karyon","html_url":"https://github.com/karyon","followers_url":"https://api.github.com/users/karyon/followers","following_url":"https://api.github.com/users/karyon/following{/other_user}","gists_url":"https://api.github.com/users/karyon/gists{/gist_id}","starred_url":"https://api.github.com/users/karyon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karyon/subscriptions","organizations_url":"https://api.github.com/users/karyon/orgs","repos_url":"https://api.github.com/users/karyon/repos","events_url":"https://api.github.com/users/karyon/events{/privacy}","received_events_url":"https://api.github.com/users/karyon/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/karyon/EvaP","description":"a university course evaluation system written in Python using Django","fork":true,"url":"https://api.github.com/repos/karyon/EvaP","forks_url":"https://api.github.com/repos/karyon/EvaP/forks","keys_url":"https://api.github.com/repos/karyon/EvaP/keys{/key_id}","collaborators_url":"https://api.github.com/repos/karyon/EvaP/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/karyon/EvaP/teams","hooks_url":"https://api.github.com/repos/karyon/EvaP/hooks","issue_events_url":"https://api.github.com/repos/karyon/EvaP/issues/events{/number}","events_url":"https://api.github.com/repos/karyon/EvaP/events","assignees_url":"https://api.github.com/repos/karyon/EvaP/assignees{/user}","branches_url":"https://api.github.com/repos/karyon/EvaP/branches{/branch}","tags_url":"https://api.github.com/repos/karyon/EvaP/tags","blobs_url":"https://api.github.com/repos/karyon/EvaP/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/karyon/EvaP/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/karyon/EvaP/git/refs{/sha}","trees_url":"https://api.github.com/repos/karyon/EvaP/git/trees{/sha}","statuses_url":"https://api.github.com/repos/karyon/EvaP/statuses/{sha}","languages_url":"https://api.github.com/repos/karyon/EvaP/languages","stargazers_url":"https://api.github.com/repos/karyon/EvaP/stargazers","contributors_url":"https://api.github.com/repos/karyon/EvaP/contributors","subscribers_url":"https://api.github.com/repos/karyon/EvaP/subscribers","subscription_url":"https://api.github.com/repos/karyon/EvaP/subscription","commits_url":"https://api.github.com/repos/karyon/EvaP/commits{/sha}","git_commits_url":"https://api.github.com/repos/karyon/EvaP/git/commits{/sha}","comments_url":"https://api.github.com/repos/karyon/EvaP/comments{/number}","issue_comment_url":"https://api.github.com/repos/karyon/EvaP/issues/comments{/number}","contents_url":"https://api.github.com/repos/karyon/EvaP/contents/{+path}","compare_url":"https://api.github.com/repos/karyon/EvaP/compare/{base}...{head}","merges_url":"https://api.github.com/repos/karyon/EvaP/merges","archive_url":"https://api.github.com/repos/karyon/EvaP/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/karyon/EvaP/downloads","issues_url":"https://api.github.com/repos/karyon/EvaP/issues{/number}","pulls_url":"https://api.github.com/repos/karyon/EvaP/pulls{/number}","milestones_url":"https://api.github.com/repos/karyon/EvaP/milestones{/number}","notifications_url":"https://api.github.com/repos/karyon/EvaP/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/karyon/EvaP/labels{/name}","releases_url":"https://api.github.com/repos/karyon/EvaP/releases{/id}","created_at":"2014-06-12T19:29:17Z","updated_at":"2015-02-28T14:36:36Z","pushed_at":"2015-04-23T09:07:18Z","git_url":"git://github.com/karyon/EvaP.git","ssh_url":"git@github.com:karyon/EvaP.git","clone_url":"https://github.com/karyon/EvaP.git","svn_url":"https://github.com/karyon/EvaP","homepage":"","size":9545,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"fsr-itse:master","ref":"master","sha":"e8cf3cde535ddf6ae20aeea6562c9eea925bb2a0","user":{"login":"fsr-itse","id":1298457,"avatar_url":"https://avatars.githubusercontent.com/u/1298457?v=3","gravatar_id":"","url":"https://api.github.com/users/fsr-itse","html_url":"https://github.com/fsr-itse","followers_url":"https://api.github.com/users/fsr-itse/followers","following_url":"https://api.github.com/users/fsr-itse/following{/other_user}","gists_url":"https://api.github.com/users/fsr-itse/gists{/gist_id}","starred_url":"https://api.github.com/users/fsr-itse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fsr-itse/subscriptions","organizations_url":"https://api.github.com/users/fsr-itse/orgs","repos_url":"https://api.github.com/users/fsr-itse/repos","events_url":"https://api.github.com/users/fsr-itse/events{/privacy}","received_events_url":"https://api.github.com/users/fsr-itse/received_events","type":"Organization","site_admin":false},"repo":{"id":3110378,"name":"EvaP","full_name":"fsr-itse/EvaP","owner":{"login":"fsr-itse","id":1298457,"avatar_url":"https://avatars.githubusercontent.com/u/1298457?v=3","gravatar_id":"","url":"https://api.github.com/users/fsr-itse","html_url":"https://github.com/fsr-itse","followers_url":"https://api.github.com/users/fsr-itse/followers","following_url":"https://api.github.com/users/fsr-itse/following{/other_user}","gists_url":"https://api.github.com/users/fsr-itse/gists{/gist_id}","starred_url":"https://api.github.com/users/fsr-itse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fsr-itse/subscriptions","organizations_url":"https://api.github.com/users/fsr-itse/orgs","repos_url":"https://api.github.com/users/fsr-itse/repos","events_url":"https://api.github.com/users/fsr-itse/events{/privacy}","received_events_url":"https://api.github.com/users/fsr-itse/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/fsr-itse/EvaP","description":"a university course evaluation system written in Python using Django","fork":false,"url":"https://api.github.com/repos/fsr-itse/EvaP","forks_url":"https://api.github.com/repos/fsr-itse/EvaP/forks","keys_url":"https://api.github.com/repos/fsr-itse/EvaP/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fsr-itse/EvaP/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fsr-itse/EvaP/teams","hooks_url":"https://api.github.com/repos/fsr-itse/EvaP/hooks","issue_events_url":"https://api.github.com/repos/fsr-itse/EvaP/issues/events{/number}","events_url":"https://api.github.com/repos/fsr-itse/EvaP/events","assignees_url":"https://api.github.com/repos/fsr-itse/EvaP/assignees{/user}","branches_url":"https://api.github.com/repos/fsr-itse/EvaP/branches{/branch}","tags_url":"https://api.github.com/repos/fsr-itse/EvaP/tags","blobs_url":"https://api.github.com/repos/fsr-itse/EvaP/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fsr-itse/EvaP/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fsr-itse/EvaP/git/refs{/sha}","trees_url":"https://api.github.com/repos/fsr-itse/EvaP/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fsr-itse/EvaP/statuses/{sha}","languages_url":"https://api.github.com/repos/fsr-itse/EvaP/languages","stargazers_url":"https://api.github.com/repos/fsr-itse/EvaP/stargazers","contributors_url":"https://api.github.com/repos/fsr-itse/EvaP/contributors","subscribers_url":"https://api.github.com/repos/fsr-itse/EvaP/subscribers","subscription_url":"https://api.github.com/repos/fsr-itse/EvaP/subscription","commits_url":"https://api.github.com/repos/fsr-itse/EvaP/commits{/sha}","git_commits_url":"https://api.github.com/repos/fsr-itse/EvaP/git/commits{/sha}","comments_url":"https://api.github.com/repos/fsr-itse/EvaP/comments{/number}","issue_comment_url":"https://api.github.com/repos/fsr-itse/EvaP/issues/comments{/number}","contents_url":"https://api.github.com/repos/fsr-itse/EvaP/contents/{+path}","compare_url":"https://api.github.com/repos/fsr-itse/EvaP/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fsr-itse/EvaP/merges","archive_url":"https://api.github.com/repos/fsr-itse/EvaP/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fsr-itse/EvaP/downloads","issues_url":"https://api.github.com/repos/fsr-itse/EvaP/issues{/number}","pulls_url":"https://api.github.com/repos/fsr-itse/EvaP/pulls{/number}","milestones_url":"https://api.github.com/repos/fsr-itse/EvaP/milestones{/number}","notifications_url":"https://api.github.com/repos/fsr-itse/EvaP/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fsr-itse/EvaP/labels{/name}","releases_url":"https://api.github.com/repos/fsr-itse/EvaP/releases{/id}","created_at":"2012-01-05T13:56:45Z","updated_at":"2015-04-23T09:02:05Z","pushed_at":"2015-04-23T09:05:21Z","git_url":"git://github.com/fsr-itse/EvaP.git","ssh_url":"git@github.com:fsr-itse/EvaP.git","clone_url":"https://github.com/fsr-itse/EvaP.git","svn_url":"https://github.com/fsr-itse/EvaP","homepage":"","size":74819,"stargazers_count":21,"watchers_count":21,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":46,"mirror_url":null,"open_issues_count":51,"forks":46,"open_issues":51,"watchers":21,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573"},"html":{"href":"https://github.com/fsr-itse/EvaP/pull/573"},"issue":{"href":"https://api.github.com/repos/fsr-itse/EvaP/issues/573"},"comments":{"href":"https://api.github.com/repos/fsr-itse/EvaP/issues/573/comments"},"review_comments":{"href":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573/comments"},"review_comment":{"href":"https://api.github.com/repos/fsr-itse/EvaP/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/fsr-itse/EvaP/pulls/573/commits"},"statuses":{"href":"https://api.github.com/repos/fsr-itse/EvaP/statuses/02a1b4613c0f614de0c435330c2b9347ca508169"}}}}