{"action":"created","comment":{"url":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/comments/78880074","id":78880074,"diff_hunk":"@@ -0,0 +1,322 @@\n+import content from '../content/index';\n+import i18n from '../i18n';\n+\n+let achievs = {};\n+let achievsContent = content.achievements;\n+let index; // must be reset in each exported function\n+\n+function contribText (contrib, backer, language) {\n+  if (!contrib && !backer) return;\n+  if (backer && backer.npc) return backer.npc;\n+  let lvl = contrib && contrib.level;\n+  if (lvl && lvl > 0) {\n+    let contribTitle = '';\n+\n+    if (lvl < 3) {\n+      contribTitle = i18n.t('friend', language);\n+    } else if (lvl < 5) {\n+      contribTitle = i18n.t('elite', language);\n+    } else if (lvl < 7) {\n+      contribTitle = i18n.t('champion', language);\n+    } else if (lvl < 8) {\n+      contribTitle = i18n.t('legendary', language);\n+    } else if (lvl < 9) {\n+      contribTitle = i18n.t('guardian', language);\n+    } else {\n+      contribTitle = i18n.t('heroic', language);\n+    }\n+\n+    return `${contribTitle} ${contrib.text}`;\n+  }\n+}\n+\n+function _add (result, data) {\n+  result[data.key] = {\n+    title: data.title,\n+    text: data.text,\n+    icon: data.icon,\n+    earned: data.earned,\n+    value: data.value,\n+    index: index++,\n+    optionalCount: data.optionalCount,\n+  };\n+}\n+\n+function _addSimpleWithCustomPath (result, user, data) {\n+  let value = user;\n+\n+  // traverse the custom path into the user object\n+  data.path.split('.').forEach(pathSeg => {","path":"common/script/libs/achievements.js","position":49,"original_position":49,"commit_id":"444152687c79bef08cffa9a5e61ece8db18a3d1b","original_commit_id":"17afdda779583762f7e47b0df129e3b248d81252","user":{"login":"crookedneighbor","id":2916945,"avatar_url":"https://avatars.githubusercontent.com/u/2916945?v=3","gravatar_id":"","url":"https://api.github.com/users/crookedneighbor","html_url":"https://github.com/crookedneighbor","followers_url":"https://api.github.com/users/crookedneighbor/followers","following_url":"https://api.github.com/users/crookedneighbor/following{/other_user}","gists_url":"https://api.github.com/users/crookedneighbor/gists{/gist_id}","starred_url":"https://api.github.com/users/crookedneighbor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crookedneighbor/subscriptions","organizations_url":"https://api.github.com/users/crookedneighbor/orgs","repos_url":"https://api.github.com/users/crookedneighbor/repos","events_url":"https://api.github.com/users/crookedneighbor/events{/privacy}","received_events_url":"https://api.github.com/users/crookedneighbor/received_events","type":"User","site_admin":false},"body":"Why not use `_.get` here?","created_at":"2016-09-15T02:24:37Z","updated_at":"2016-09-15T02:27:18Z","html_url":"https://github.com/HabitRPG/habitrpg/pull/7904#discussion_r78880074","pull_request_url":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904","_links":{"self":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/comments/78880074"},"html":{"href":"https://github.com/HabitRPG/habitrpg/pull/7904#discussion_r78880074"},"pull_request":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904"}}},"pull_request":{"url":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904","id":81416635,"html_url":"https://github.com/HabitRPG/habitrpg/pull/7904","diff_url":"https://github.com/HabitRPG/habitrpg/pull/7904.diff","patch_url":"https://github.com/HabitRPG/habitrpg/pull/7904.patch","issue_url":"https://api.github.com/repos/HabitRPG/habitrpg/issues/7904","number":7904,"state":"open","locked":false,"title":"Achievement list renovation & Achievements API","user":{"login":"khipkin","id":5641207,"avatar_url":"https://avatars.githubusercontent.com/u/5641207?v=3","gravatar_id":"","url":"https://api.github.com/users/khipkin","html_url":"https://github.com/khipkin","followers_url":"https://api.github.com/users/khipkin/followers","following_url":"https://api.github.com/users/khipkin/following{/other_user}","gists_url":"https://api.github.com/users/khipkin/gists{/gist_id}","starred_url":"https://api.github.com/users/khipkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/khipkin/subscriptions","organizations_url":"https://api.github.com/users/khipkin/orgs","repos_url":"https://api.github.com/users/khipkin/repos","events_url":"https://api.github.com/users/khipkin/events{/privacy}","received_events_url":"https://api.github.com/users/khipkin/received_events","type":"User","site_admin":false},"body":"[//]: # (Put Issue # or URL here, if applicable. This will automatically close the issue if your PR is merged in)\r\nFixes #2893\r\n\r\n## Changes\r\n\r\n- [x] Divided all possible achievements into three categories: Basic, Seasonal, and Special.\r\n\r\n    1. **Basic**: Streaks, Perfect Days, Party Up, Party On, Beast Master, Mount Master, Triad Bingo, Healer Ultimate Gear, Rogue Ultimate Gear, Warrior Ultimate Gear, Mage Ultimate Gear, Rebirth\r\n    2.  **Seasonal**: Habitica Day, Habit Birthday, Annoying Friends (Snowballs), Alarming Friends (Spooky Sparkles), Agricultural Friends (Shiny Seeds), Aquatic Friends (Seafoam), Dilatory World Quest, Stressbeast World Quest, Burnout World Quest, Bewilder World Quest, Costume Contest, Greeting Cards, Thank You Cards, NYE Cards, Valentine Cards, Birthday Cards\r\n    3.  **Special**: Habitica Surveys, Contributor, _NPC Backer_, _Backer (Any Tier)_, _Veteran_, _Original User_\r\n\r\n\r\n_(Italicized achievements are only shown if they are achieved; otherwise they are hidden so that users aren't disheartened by visible-yet-unachievable achievements.)_\r\n\r\n\r\n- [x] Unachieved achievements are now always shown, regardless of whether the profile being viewed is yours or someone else's.  (Note: this does not include the special-case achievements mentioned above.)\r\n\r\n\r\n- [x] Made achievement strings more consistent.  (See discussion on #2893 for details.)\r\n\r\n    - Replaced manual string concatenation with parameterized string interpolation.\r\n    - Achievements with singular-vs-plural structures now consistently use the singular form when the count is exactly 1 or when the achievement is not achieved (in which case, the achievement is muted), otherwise the plural form is used.\r\n\r\n\r\n\r\n- [x] Added count bubbles for applicable achievements when they are achieved.  This only applies to non-binary achievements.  (For example, party up/on, ultimate gear, etc. would not have counts.)\r\n\r\n\r\n- [x] Show achievements in a grid display (similar to the Pets/Mounts grids).\r\n\r\n    - Each achievement uses a 2x (aka large) badge as its image.  The achievement title and description appear in a popup on mouseover.\r\n        - [x] Added any 2x images that were missing.\r\n    - Each achievement shows the normal (colored) badge if it is achieved; otherwise, it shows the special, dark \"unachieved\" badge.\r\n        - [x] Added a 2x \"unachieved\" badge (credit to @tricksyfox) to be displayed for unearned achievements (except the hidden-if-unachieved special ones).\r\n\r\n\r\n- [x] @negue and I added an achievement API!  This makes it possible to list a user's achievements using the following route: `/member/{memberId}/achievements`.  The returned object will look something like this, with the format of each achievement over on the right:\r\n![image](https://cloud.githubusercontent.com/assets/5641207/18235987/72fb1000-72ef-11e6-8904-333d233f7cee.png)\r\n\r\n## Remaining Questions\r\n\r\n- [ ] Some of the achievement descriptions contain links to pages with additional information.  How can we make the popovers stick around long enough for users to click on the links?  Maybe clicking on the achievement icon makes its popover persist until clicked again?\r\n\r\n- [ ] Should the formatting of the popover text change for achieved vs unachieved achievements?  For example: previously, unachieved titles/descriptions were previously `muted`, meaning the text was gray.  Maybe that could still be the case, with the text in the popover being `muted` in addition to the dark \"unearned\" badge?  (See discussion on #2893 for examples and screenshots.)\r\n\r\n- [ ] Some achievements (notably the Contributor and Backer achievements) previously used colored spans in the achievement titles to highlight the special status of the user's contributions.  Should these colors be used somehow in the new layout?  If so, how?\r\n\r\n## Screenshots\r\n\r\n_The layout of the achievements with the survey and contributor achievements in the \"Special\" section, with the hidden-if-unachieved achievements both shown and hidden.  This screenshot does not include counts._\r\n\r\n![image](https://cloud.githubusercontent.com/assets/5641207/17673493/5c9cd678-62ef-11e6-98b1-3ac56c7ffab3.png)\r\n\r\n_An example achievement grid for a user, with both achieved and unachieved achievements shown.  Applicable achieved achievements show the count bubbles._\r\n\r\n![image](https://cloud.githubusercontent.com/assets/5641207/17985491/18f62b8e-6ae4-11e6-9362-407003bb85ad.png)\r\n\r\n_Sample popover for the \"Streak\" achievement, with the mouse position indicated in red._\r\n\r\n![image](https://cloud.githubusercontent.com/assets/5641207/18257327/be6d7eb0-738f-11e6-8260-c82730aa15cd.png)\r\n\r\n_The new achievements grid as seen in a member modal._\r\n\r\n![image](https://cloud.githubusercontent.com/assets/5641207/18255003/447117c4-7372-11e6-8ff2-060cbe08b7a2.png)","created_at":"2016-08-16T05:32:29Z","updated_at":"2016-09-15T02:27:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"907f7f99126cbee7b60eaf23e8223bc1b55c1395","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904/commits","review_comments_url":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904/comments","review_comment_url":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/comments{/number}","comments_url":"https://api.github.com/repos/HabitRPG/habitrpg/issues/7904/comments","statuses_url":"https://api.github.com/repos/HabitRPG/habitrpg/statuses/444152687c79bef08cffa9a5e61ece8db18a3d1b","head":{"label":"khipkin:achiev_list_renovation","ref":"achiev_list_renovation","sha":"444152687c79bef08cffa9a5e61ece8db18a3d1b","user":{"login":"khipkin","id":5641207,"avatar_url":"https://avatars.githubusercontent.com/u/5641207?v=3","gravatar_id":"","url":"https://api.github.com/users/khipkin","html_url":"https://github.com/khipkin","followers_url":"https://api.github.com/users/khipkin/followers","following_url":"https://api.github.com/users/khipkin/following{/other_user}","gists_url":"https://api.github.com/users/khipkin/gists{/gist_id}","starred_url":"https://api.github.com/users/khipkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/khipkin/subscriptions","organizations_url":"https://api.github.com/users/khipkin/orgs","repos_url":"https://api.github.com/users/khipkin/repos","events_url":"https://api.github.com/users/khipkin/events{/privacy}","received_events_url":"https://api.github.com/users/khipkin/received_events","type":"User","site_admin":false},"repo":{"id":52041602,"name":"habitrpg","full_name":"khipkin/habitrpg","owner":{"login":"khipkin","id":5641207,"avatar_url":"https://avatars.githubusercontent.com/u/5641207?v=3","gravatar_id":"","url":"https://api.github.com/users/khipkin","html_url":"https://github.com/khipkin","followers_url":"https://api.github.com/users/khipkin/followers","following_url":"https://api.github.com/users/khipkin/following{/other_user}","gists_url":"https://api.github.com/users/khipkin/gists{/gist_id}","starred_url":"https://api.github.com/users/khipkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/khipkin/subscriptions","organizations_url":"https://api.github.com/users/khipkin/orgs","repos_url":"https://api.github.com/users/khipkin/repos","events_url":"https://api.github.com/users/khipkin/events{/privacy}","received_events_url":"https://api.github.com/users/khipkin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/khipkin/habitrpg","description":"A habit tracker app which treats your goals like a Role Playing Game.","fork":true,"url":"https://api.github.com/repos/khipkin/habitrpg","forks_url":"https://api.github.com/repos/khipkin/habitrpg/forks","keys_url":"https://api.github.com/repos/khipkin/habitrpg/keys{/key_id}","collaborators_url":"https://api.github.com/repos/khipkin/habitrpg/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/khipkin/habitrpg/teams","hooks_url":"https://api.github.com/repos/khipkin/habitrpg/hooks","issue_events_url":"https://api.github.com/repos/khipkin/habitrpg/issues/events{/number}","events_url":"https://api.github.com/repos/khipkin/habitrpg/events","assignees_url":"https://api.github.com/repos/khipkin/habitrpg/assignees{/user}","branches_url":"https://api.github.com/repos/khipkin/habitrpg/branches{/branch}","tags_url":"https://api.github.com/repos/khipkin/habitrpg/tags","blobs_url":"https://api.github.com/repos/khipkin/habitrpg/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/khipkin/habitrpg/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/khipkin/habitrpg/git/refs{/sha}","trees_url":"https://api.github.com/repos/khipkin/habitrpg/git/trees{/sha}","statuses_url":"https://api.github.com/repos/khipkin/habitrpg/statuses/{sha}","languages_url":"https://api.github.com/repos/khipkin/habitrpg/languages","stargazers_url":"https://api.github.com/repos/khipkin/habitrpg/stargazers","contributors_url":"https://api.github.com/repos/khipkin/habitrpg/contributors","subscribers_url":"https://api.github.com/repos/khipkin/habitrpg/subscribers","subscription_url":"https://api.github.com/repos/khipkin/habitrpg/subscription","commits_url":"https://api.github.com/repos/khipkin/habitrpg/commits{/sha}","git_commits_url":"https://api.github.com/repos/khipkin/habitrpg/git/commits{/sha}","comments_url":"https://api.github.com/repos/khipkin/habitrpg/comments{/number}","issue_comment_url":"https://api.github.com/repos/khipkin/habitrpg/issues/comments{/number}","contents_url":"https://api.github.com/repos/khipkin/habitrpg/contents/{+path}","compare_url":"https://api.github.com/repos/khipkin/habitrpg/compare/{base}...{head}","merges_url":"https://api.github.com/repos/khipkin/habitrpg/merges","archive_url":"https://api.github.com/repos/khipkin/habitrpg/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/khipkin/habitrpg/downloads","issues_url":"https://api.github.com/repos/khipkin/habitrpg/issues{/number}","pulls_url":"https://api.github.com/repos/khipkin/habitrpg/pulls{/number}","milestones_url":"https://api.github.com/repos/khipkin/habitrpg/milestones{/number}","notifications_url":"https://api.github.com/repos/khipkin/habitrpg/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/khipkin/habitrpg/labels{/name}","releases_url":"https://api.github.com/repos/khipkin/habitrpg/releases{/id}","deployments_url":"https://api.github.com/repos/khipkin/habitrpg/deployments","created_at":"2016-02-18T21:54:20Z","updated_at":"2016-02-18T21:54:28Z","pushed_at":"2016-09-15T01:54:26Z","git_url":"git://github.com/khipkin/habitrpg.git","ssh_url":"git@github.com:khipkin/habitrpg.git","clone_url":"https://github.com/khipkin/habitrpg.git","svn_url":"https://github.com/khipkin/habitrpg","homepage":"https://habitica.com","size":467087,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","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":"develop"}},"base":{"label":"HabitRPG:develop","ref":"develop","sha":"a4fd687510160fc54e5730266f4f921f63f49c53","user":{"login":"HabitRPG","id":3834775,"avatar_url":"https://avatars.githubusercontent.com/u/3834775?v=3","gravatar_id":"","url":"https://api.github.com/users/HabitRPG","html_url":"https://github.com/HabitRPG","followers_url":"https://api.github.com/users/HabitRPG/followers","following_url":"https://api.github.com/users/HabitRPG/following{/other_user}","gists_url":"https://api.github.com/users/HabitRPG/gists{/gist_id}","starred_url":"https://api.github.com/users/HabitRPG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HabitRPG/subscriptions","organizations_url":"https://api.github.com/users/HabitRPG/orgs","repos_url":"https://api.github.com/users/HabitRPG/repos","events_url":"https://api.github.com/users/HabitRPG/events{/privacy}","received_events_url":"https://api.github.com/users/HabitRPG/received_events","type":"Organization","site_admin":false},"repo":{"id":4578898,"name":"habitrpg","full_name":"HabitRPG/habitrpg","owner":{"login":"HabitRPG","id":3834775,"avatar_url":"https://avatars.githubusercontent.com/u/3834775?v=3","gravatar_id":"","url":"https://api.github.com/users/HabitRPG","html_url":"https://github.com/HabitRPG","followers_url":"https://api.github.com/users/HabitRPG/followers","following_url":"https://api.github.com/users/HabitRPG/following{/other_user}","gists_url":"https://api.github.com/users/HabitRPG/gists{/gist_id}","starred_url":"https://api.github.com/users/HabitRPG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HabitRPG/subscriptions","organizations_url":"https://api.github.com/users/HabitRPG/orgs","repos_url":"https://api.github.com/users/HabitRPG/repos","events_url":"https://api.github.com/users/HabitRPG/events{/privacy}","received_events_url":"https://api.github.com/users/HabitRPG/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/HabitRPG/habitrpg","description":"A habit tracker app which treats your goals like a Role Playing Game.","fork":false,"url":"https://api.github.com/repos/HabitRPG/habitrpg","forks_url":"https://api.github.com/repos/HabitRPG/habitrpg/forks","keys_url":"https://api.github.com/repos/HabitRPG/habitrpg/keys{/key_id}","collaborators_url":"https://api.github.com/repos/HabitRPG/habitrpg/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/HabitRPG/habitrpg/teams","hooks_url":"https://api.github.com/repos/HabitRPG/habitrpg/hooks","issue_events_url":"https://api.github.com/repos/HabitRPG/habitrpg/issues/events{/number}","events_url":"https://api.github.com/repos/HabitRPG/habitrpg/events","assignees_url":"https://api.github.com/repos/HabitRPG/habitrpg/assignees{/user}","branches_url":"https://api.github.com/repos/HabitRPG/habitrpg/branches{/branch}","tags_url":"https://api.github.com/repos/HabitRPG/habitrpg/tags","blobs_url":"https://api.github.com/repos/HabitRPG/habitrpg/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/HabitRPG/habitrpg/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/HabitRPG/habitrpg/git/refs{/sha}","trees_url":"https://api.github.com/repos/HabitRPG/habitrpg/git/trees{/sha}","statuses_url":"https://api.github.com/repos/HabitRPG/habitrpg/statuses/{sha}","languages_url":"https://api.github.com/repos/HabitRPG/habitrpg/languages","stargazers_url":"https://api.github.com/repos/HabitRPG/habitrpg/stargazers","contributors_url":"https://api.github.com/repos/HabitRPG/habitrpg/contributors","subscribers_url":"https://api.github.com/repos/HabitRPG/habitrpg/subscribers","subscription_url":"https://api.github.com/repos/HabitRPG/habitrpg/subscription","commits_url":"https://api.github.com/repos/HabitRPG/habitrpg/commits{/sha}","git_commits_url":"https://api.github.com/repos/HabitRPG/habitrpg/git/commits{/sha}","comments_url":"https://api.github.com/repos/HabitRPG/habitrpg/comments{/number}","issue_comment_url":"https://api.github.com/repos/HabitRPG/habitrpg/issues/comments{/number}","contents_url":"https://api.github.com/repos/HabitRPG/habitrpg/contents/{+path}","compare_url":"https://api.github.com/repos/HabitRPG/habitrpg/compare/{base}...{head}","merges_url":"https://api.github.com/repos/HabitRPG/habitrpg/merges","archive_url":"https://api.github.com/repos/HabitRPG/habitrpg/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/HabitRPG/habitrpg/downloads","issues_url":"https://api.github.com/repos/HabitRPG/habitrpg/issues{/number}","pulls_url":"https://api.github.com/repos/HabitRPG/habitrpg/pulls{/number}","milestones_url":"https://api.github.com/repos/HabitRPG/habitrpg/milestones{/number}","notifications_url":"https://api.github.com/repos/HabitRPG/habitrpg/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/HabitRPG/habitrpg/labels{/name}","releases_url":"https://api.github.com/repos/HabitRPG/habitrpg/releases{/id}","deployments_url":"https://api.github.com/repos/HabitRPG/habitrpg/deployments","created_at":"2012-06-06T22:49:48Z","updated_at":"2016-09-14T12:06:25Z","pushed_at":"2016-09-15T01:54:27Z","git_url":"git://github.com/HabitRPG/habitrpg.git","ssh_url":"git@github.com:HabitRPG/habitrpg.git","clone_url":"https://github.com/HabitRPG/habitrpg.git","svn_url":"https://github.com/HabitRPG/habitrpg","homepage":"https://habitica.com","size":520419,"stargazers_count":4175,"watchers_count":4175,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1752,"mirror_url":null,"open_issues_count":343,"forks":1752,"open_issues":343,"watchers":4175,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904"},"html":{"href":"https://github.com/HabitRPG/habitrpg/pull/7904"},"issue":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/issues/7904"},"comments":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/issues/7904/comments"},"review_comments":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904/comments"},"review_comment":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/pulls/7904/commits"},"statuses":{"href":"https://api.github.com/repos/HabitRPG/habitrpg/statuses/444152687c79bef08cffa9a5e61ece8db18a3d1b"}}}}
{"actor":{"display_login":"crookedneighbor"}}