{"action":"created","comment":{"url":"https://api.github.com/repos/wagn/wikirate/pulls/comments/45935231","id":45935231,"diff_hunk":"@@ -0,0 +1,127 @@\n+WL_FORMULA_WHITELIST = ::Set.new ['Boole']\n+\n+def metric_name\n+  cardname.left\n+end\n+\n+event :approve_formula, before: :approve do\n+  not_on_whitelist =\n+    content.gsub(/\\{\\{([^}])+\\}\\}/,'').scan(/[a-zA-Z][a-zA-Z]+/)\n+    .reject do |word|\n+      WL_FORMULA_WHITELIST.include? word\n+    end\n+  if not_on_whitelist.present?\n+    errors.add :formula, \"#{not_on_whitelist.first} forbidden keyword\"\n+  end\n+end\n+\n+event :update_scores_for_formula, on: :update, before: :approve,\n+                         when: proc { |c| !c.supercard } do # don't update if it's part of scored metric update\n+  add_subcard left\n+  left.update_values\n+end\n+\n+event :create_scores_for_formula, on: :create, before: :approve,\n+                         when: proc { |c| !c.supercard } do # don't update if it's part of scored metric create\n+  add_subcard left\n+  left.create_values\n+end\n+\n+\n+def calculate_all_values\n+  formula_interpreter.evaluate.each_pair do |year, companies|\n+    companies.each_pair do |company, value|\n+      yield company, year, value\n+    end\n+  end\n+end\n+\n+def calculate_values_for company\n+  values = fetch_input_values company: company\n+  values.each_pair do |year, companies|\n+    metrics_with_values = companies[company.to_name.key]\n+    value = formula_interpreter.evaluate_single_input metrics_with_values\n+    yield year, value\n+  end\n+end\n+\n+\n+def keyified\n+  content.gsub(/\\{\\{\\s*([^}]+)\\s*\\}\\}/) do |_match|\n+    \"{{#{$1.to_name.key}}}\"\n+  end\n+end\n+\n+private\n+\n+def formula_interpreter\n+  if ruby_formula?\n+    RubyFormula.new(self)\n+  else\n+    WolframFormula.new(self)\n+  end\n+end\n+\n+def input_values\n+  @input_values ||= fetch_input_values\n+end\n+\n+def input_metric_keys\n+  @metric_keys ||= extract_metrics.map { |m| m.to_name.key }\n+end\n+\n+def extract_metrics\n+  content.scan(/\\{\\{([^}]+)\\}\\}/).flatten\n+end\n+\n+# allow only numbers, whitespace, mathematical operations and args references\n+def ruby_formula?\n+  content.gsub(/\\{\\{([^}])+\\}\\}/,'').match(/^[\\s\\d+-\\/*\\.()]*$/)\n+end\n+\n+# choose a company or fetch all values\n+def fetch_input_values opts={}\n+  values = Hash.new { |h1, k1| h1[k1] = Hash.new { |h2, k2| h2[k2] = {} } }\n+  return values if input_metric_keys.empty?\n+  value_cards =\n+    if opts[:company]\n+      input_value_cards_for opts[:company]\n+    else\n+      all_input_value_cards\n+    end\n+\n+  value_cards.each do |v_card|\n+    year = v_card.cardname.left_name.right\n+    company = v_card.cardname.left_name.left_name.right_name.key\n+    metric = v_card.cardname.left_name.left_name.left_name.key\n+    values[year][company][metric] = v_card.content\n+  end\n+  values\n+end\n+\n+def normalize_value value\n+  ('%.1f' % value).gsub(/\\.0$/, '')\n+end\n+\n+def all_input_value_cards\n+  Card.search value_cards_query(metrics: input_metric_keys)\n+end\n+\n+def input_value_cards_for company\n+  Card.search value_cards_query(company: company, metrics: input_metrics_keys)\n+end\n+\n+def value_cards_query opts={}\n+  metrics = opts[:metrics].is_a?(Array) ? opts[:metrics].unshift('in') :","path":"mod/01_rating/set/type_plus_right/metric/formula.rb","position":115,"original_position":115,"commit_id":"34393f0d2c8b86bb24860116fb650db9ee6bef84","original_commit_id":"34393f0d2c8b86bb24860116fb650db9ee6bef84","user":{"login":"houndci","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci","html_url":"https://github.com/houndci","followers_url":"https://api.github.com/users/houndci/followers","following_url":"https://api.github.com/users/houndci/following{/other_user}","gists_url":"https://api.github.com/users/houndci/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci/subscriptions","organizations_url":"https://api.github.com/users/houndci/orgs","repos_url":"https://api.github.com/users/houndci/repos","events_url":"https://api.github.com/users/houndci/events{/privacy}","received_events_url":"https://api.github.com/users/houndci/received_events","type":"User","site_admin":false},"body":"Avoid multi-line ?: (the ternary operator); use `if`/`unless` instead.","created_at":"2015-11-26T00:50:49Z","updated_at":"2015-11-26T00:50:49Z","html_url":"https://github.com/wagn/wikirate/pull/284#discussion_r45935231","pull_request_url":"https://api.github.com/repos/wagn/wikirate/pulls/284","_links":{"self":{"href":"https://api.github.com/repos/wagn/wikirate/pulls/comments/45935231"},"html":{"href":"https://github.com/wagn/wikirate/pull/284#discussion_r45935231"},"pull_request":{"href":"https://api.github.com/repos/wagn/wikirate/pulls/284"}}},"pull_request":{"url":"https://api.github.com/repos/wagn/wikirate/pulls/284","id":51659581,"html_url":"https://github.com/wagn/wikirate/pull/284","diff_url":"https://github.com/wagn/wikirate/pull/284.diff","patch_url":"https://github.com/wagn/wikirate/pull/284.patch","issue_url":"https://api.github.com/repos/wagn/wikirate/issues/284","number":284,"state":"open","locked":false,"title":"ratings","user":{"login":"xithan","id":13584,"avatar_url":"https://avatars.githubusercontent.com/u/13584?v=3","gravatar_id":"","url":"https://api.github.com/users/xithan","html_url":"https://github.com/xithan","followers_url":"https://api.github.com/users/xithan/followers","following_url":"https://api.github.com/users/xithan/following{/other_user}","gists_url":"https://api.github.com/users/xithan/gists{/gist_id}","starred_url":"https://api.github.com/users/xithan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xithan/subscriptions","organizations_url":"https://api.github.com/users/xithan/orgs","repos_url":"https://api.github.com/users/xithan/repos","events_url":"https://api.github.com/users/xithan/events{/privacy}","received_events_url":"https://api.github.com/users/xithan/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-11-24T13:31:55Z","updated_at":"2015-11-26T00:50:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3d713f7094fc44674e7a3d2084c764f5f33aff40","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/wagn/wikirate/pulls/284/commits","review_comments_url":"https://api.github.com/repos/wagn/wikirate/pulls/284/comments","review_comment_url":"https://api.github.com/repos/wagn/wikirate/pulls/comments{/number}","comments_url":"https://api.github.com/repos/wagn/wikirate/issues/284/comments","statuses_url":"https://api.github.com/repos/wagn/wikirate/statuses/34393f0d2c8b86bb24860116fb650db9ee6bef84","head":{"label":"xithan:ratings","ref":"ratings","sha":"34393f0d2c8b86bb24860116fb650db9ee6bef84","user":{"login":"xithan","id":13584,"avatar_url":"https://avatars.githubusercontent.com/u/13584?v=3","gravatar_id":"","url":"https://api.github.com/users/xithan","html_url":"https://github.com/xithan","followers_url":"https://api.github.com/users/xithan/followers","following_url":"https://api.github.com/users/xithan/following{/other_user}","gists_url":"https://api.github.com/users/xithan/gists{/gist_id}","starred_url":"https://api.github.com/users/xithan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xithan/subscriptions","organizations_url":"https://api.github.com/users/xithan/orgs","repos_url":"https://api.github.com/users/xithan/repos","events_url":"https://api.github.com/users/xithan/events{/privacy}","received_events_url":"https://api.github.com/users/xithan/received_events","type":"User","site_admin":false},"repo":{"id":20190741,"name":"wikirate","full_name":"xithan/wikirate","owner":{"login":"xithan","id":13584,"avatar_url":"https://avatars.githubusercontent.com/u/13584?v=3","gravatar_id":"","url":"https://api.github.com/users/xithan","html_url":"https://github.com/xithan","followers_url":"https://api.github.com/users/xithan/followers","following_url":"https://api.github.com/users/xithan/following{/other_user}","gists_url":"https://api.github.com/users/xithan/gists{/gist_id}","starred_url":"https://api.github.com/users/xithan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xithan/subscriptions","organizations_url":"https://api.github.com/users/xithan/orgs","repos_url":"https://api.github.com/users/xithan/repos","events_url":"https://api.github.com/users/xithan/events{/privacy}","received_events_url":"https://api.github.com/users/xithan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/xithan/wikirate","description":"","fork":true,"url":"https://api.github.com/repos/xithan/wikirate","forks_url":"https://api.github.com/repos/xithan/wikirate/forks","keys_url":"https://api.github.com/repos/xithan/wikirate/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xithan/wikirate/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xithan/wikirate/teams","hooks_url":"https://api.github.com/repos/xithan/wikirate/hooks","issue_events_url":"https://api.github.com/repos/xithan/wikirate/issues/events{/number}","events_url":"https://api.github.com/repos/xithan/wikirate/events","assignees_url":"https://api.github.com/repos/xithan/wikirate/assignees{/user}","branches_url":"https://api.github.com/repos/xithan/wikirate/branches{/branch}","tags_url":"https://api.github.com/repos/xithan/wikirate/tags","blobs_url":"https://api.github.com/repos/xithan/wikirate/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xithan/wikirate/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xithan/wikirate/git/refs{/sha}","trees_url":"https://api.github.com/repos/xithan/wikirate/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xithan/wikirate/statuses/{sha}","languages_url":"https://api.github.com/repos/xithan/wikirate/languages","stargazers_url":"https://api.github.com/repos/xithan/wikirate/stargazers","contributors_url":"https://api.github.com/repos/xithan/wikirate/contributors","subscribers_url":"https://api.github.com/repos/xithan/wikirate/subscribers","subscription_url":"https://api.github.com/repos/xithan/wikirate/subscription","commits_url":"https://api.github.com/repos/xithan/wikirate/commits{/sha}","git_commits_url":"https://api.github.com/repos/xithan/wikirate/git/commits{/sha}","comments_url":"https://api.github.com/repos/xithan/wikirate/comments{/number}","issue_comment_url":"https://api.github.com/repos/xithan/wikirate/issues/comments{/number}","contents_url":"https://api.github.com/repos/xithan/wikirate/contents/{+path}","compare_url":"https://api.github.com/repos/xithan/wikirate/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xithan/wikirate/merges","archive_url":"https://api.github.com/repos/xithan/wikirate/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xithan/wikirate/downloads","issues_url":"https://api.github.com/repos/xithan/wikirate/issues{/number}","pulls_url":"https://api.github.com/repos/xithan/wikirate/pulls{/number}","milestones_url":"https://api.github.com/repos/xithan/wikirate/milestones{/number}","notifications_url":"https://api.github.com/repos/xithan/wikirate/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xithan/wikirate/labels{/name}","releases_url":"https://api.github.com/repos/xithan/wikirate/releases{/id}","created_at":"2014-05-26T15:35:11Z","updated_at":"2015-05-09T14:42:27Z","pushed_at":"2015-11-26T00:50:40Z","git_url":"git://github.com/xithan/wikirate.git","ssh_url":"git@github.com:xithan/wikirate.git","clone_url":"https://github.com/xithan/wikirate.git","svn_url":"https://github.com/xithan/wikirate","homepage":null,"size":87204,"stargazers_count":0,"watchers_count":0,"language":"Java","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":"wagn:master","ref":"master","sha":"f2d393340c81a9e85ca11349dfc821019138e17b","user":{"login":"wagn","id":20722,"avatar_url":"https://avatars.githubusercontent.com/u/20722?v=3","gravatar_id":"","url":"https://api.github.com/users/wagn","html_url":"https://github.com/wagn","followers_url":"https://api.github.com/users/wagn/followers","following_url":"https://api.github.com/users/wagn/following{/other_user}","gists_url":"https://api.github.com/users/wagn/gists{/gist_id}","starred_url":"https://api.github.com/users/wagn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wagn/subscriptions","organizations_url":"https://api.github.com/users/wagn/orgs","repos_url":"https://api.github.com/users/wagn/repos","events_url":"https://api.github.com/users/wagn/events{/privacy}","received_events_url":"https://api.github.com/users/wagn/received_events","type":"User","site_admin":false},"repo":{"id":15884166,"name":"wikirate","full_name":"wagn/wikirate","owner":{"login":"wagn","id":20722,"avatar_url":"https://avatars.githubusercontent.com/u/20722?v=3","gravatar_id":"","url":"https://api.github.com/users/wagn","html_url":"https://github.com/wagn","followers_url":"https://api.github.com/users/wagn/followers","following_url":"https://api.github.com/users/wagn/following{/other_user}","gists_url":"https://api.github.com/users/wagn/gists{/gist_id}","starred_url":"https://api.github.com/users/wagn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wagn/subscriptions","organizations_url":"https://api.github.com/users/wagn/orgs","repos_url":"https://api.github.com/users/wagn/repos","events_url":"https://api.github.com/users/wagn/events{/privacy}","received_events_url":"https://api.github.com/users/wagn/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/wagn/wikirate","description":"","fork":false,"url":"https://api.github.com/repos/wagn/wikirate","forks_url":"https://api.github.com/repos/wagn/wikirate/forks","keys_url":"https://api.github.com/repos/wagn/wikirate/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wagn/wikirate/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wagn/wikirate/teams","hooks_url":"https://api.github.com/repos/wagn/wikirate/hooks","issue_events_url":"https://api.github.com/repos/wagn/wikirate/issues/events{/number}","events_url":"https://api.github.com/repos/wagn/wikirate/events","assignees_url":"https://api.github.com/repos/wagn/wikirate/assignees{/user}","branches_url":"https://api.github.com/repos/wagn/wikirate/branches{/branch}","tags_url":"https://api.github.com/repos/wagn/wikirate/tags","blobs_url":"https://api.github.com/repos/wagn/wikirate/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wagn/wikirate/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wagn/wikirate/git/refs{/sha}","trees_url":"https://api.github.com/repos/wagn/wikirate/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wagn/wikirate/statuses/{sha}","languages_url":"https://api.github.com/repos/wagn/wikirate/languages","stargazers_url":"https://api.github.com/repos/wagn/wikirate/stargazers","contributors_url":"https://api.github.com/repos/wagn/wikirate/contributors","subscribers_url":"https://api.github.com/repos/wagn/wikirate/subscribers","subscription_url":"https://api.github.com/repos/wagn/wikirate/subscription","commits_url":"https://api.github.com/repos/wagn/wikirate/commits{/sha}","git_commits_url":"https://api.github.com/repos/wagn/wikirate/git/commits{/sha}","comments_url":"https://api.github.com/repos/wagn/wikirate/comments{/number}","issue_comment_url":"https://api.github.com/repos/wagn/wikirate/issues/comments{/number}","contents_url":"https://api.github.com/repos/wagn/wikirate/contents/{+path}","compare_url":"https://api.github.com/repos/wagn/wikirate/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wagn/wikirate/merges","archive_url":"https://api.github.com/repos/wagn/wikirate/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wagn/wikirate/downloads","issues_url":"https://api.github.com/repos/wagn/wikirate/issues{/number}","pulls_url":"https://api.github.com/repos/wagn/wikirate/pulls{/number}","milestones_url":"https://api.github.com/repos/wagn/wikirate/milestones{/number}","notifications_url":"https://api.github.com/repos/wagn/wikirate/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wagn/wikirate/labels{/name}","releases_url":"https://api.github.com/repos/wagn/wikirate/releases{/id}","created_at":"2014-01-13T22:29:39Z","updated_at":"2015-05-08T17:01:43Z","pushed_at":"2015-11-26T00:50:41Z","git_url":"git://github.com/wagn/wikirate.git","ssh_url":"git@github.com:wagn/wikirate.git","clone_url":"https://github.com/wagn/wikirate.git","svn_url":"https://github.com/wagn/wikirate","homepage":null,"size":85805,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":1,"forks":5,"open_issues":1,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/wagn/wikirate/pulls/284"},"html":{"href":"https://github.com/wagn/wikirate/pull/284"},"issue":{"href":"https://api.github.com/repos/wagn/wikirate/issues/284"},"comments":{"href":"https://api.github.com/repos/wagn/wikirate/issues/284/comments"},"review_comments":{"href":"https://api.github.com/repos/wagn/wikirate/pulls/284/comments"},"review_comment":{"href":"https://api.github.com/repos/wagn/wikirate/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/wagn/wikirate/pulls/284/commits"},"statuses":{"href":"https://api.github.com/repos/wagn/wikirate/statuses/34393f0d2c8b86bb24860116fb650db9ee6bef84"}}}}