{"action":"created","comment":{"url":"https://api.github.com/repos/tgstation/tgstation/pulls/comments/126144200","pull_request_review_id":48602477,"id":126144200,"diff_hunk":"@@ -0,0 +1,333 @@\n+GLOBAL_LIST_EMPTY(exp_to_update)\n+GLOBAL_PROTECT(exp_to_update)\n+\n+// Admin Verbs\n+/client/proc/cmd_admin_check_player_exp()\t//Allows admins to determine who the newer players are.\n+\tset category = \"Admin\"\n+\tset name = \"Check Player Playtime\"\n+\tif(!check_rights(R_ADMIN))\n+\t\treturn\n+\tvar/list/msg = list()\n+\tmsg += \"<html><head><title>Playtime Report</title></head><body>Playtime:<BR><UL>\"\n+\tfor(var/client/C in GLOB.clients)\n+\t\tmsg += \"<LI> - [key_name_admin(C)]: <A href='?_src_=holder;getplaytimewindow=\\ref[C.mob]'>\" + C.get_exp_living() + \"</a></LI>\"\n+\tmsg += \"</UL></BODY></HTML>\"\n+\tsrc << browse(msg.Join(), \"window=Player_playtime_check\")\n+\n+/datum/admins/proc/cmd_show_exp_panel(client/C)\n+\tif(!C)\n+\t\tto_chat(usr, \"ERROR: Client not found.\")\n+\t\treturn\n+\tif(!check_rights(R_ADMIN))\n+\t\treturn\n+\tvar/list/body = list()\n+\tbody += \"<html><head><title>Playtime for [C.key]</title></head><BODY><BR>Playtime:\"\n+\tbody += C.get_exp_report()\n+\tbody += \"<A href='?_src_=holder;toggleexempt=\\ref[C]'>Toggle Exempt status</a>\"\n+\tbody += \"</BODY></HTML>\"\n+\tusr << browse(body.Join(), \"window=playerplaytime[C.ckey];size=550x615\")\n+\n+\n+/datum/admins/proc/toggle_exempt_status(client/C)\n+\tif(!C)\n+\t\tto_chat(usr, \"ERROR: Client not found.\")\n+\t\treturn\n+\tif(!check_rights(R_ADMIN))\n+\t\treturn\n+\n+\tset_db_player_flags(C)\n+\tvar/dbflags = C.prefs.db_flags\n+\tvar/newstate = FALSE\n+\tif(dbflags & DB_FLAG_EXEMPT)\n+\t\tnewstate = FALSE\n+\telse\n+\t\tnewstate = TRUE\n+\n+\tmessage_admins(\"[key_name_admin(usr)] has [newstate ? \"activated\" : \"deactivated\"] job exp exempt status on [key_name_admin(C)]\")\n+\tupdate_flag_db(C,DB_FLAG_EXEMPT, newstate)\n+\n+// Procs\n+\n+\n+/datum/job/proc/required_playtime_remaining(client/C)\n+\tif(!C)\n+\t\treturn 0\n+\tif(!config.use_exp_tracking)\n+\t\treturn 0\n+\tif(!exp_requirements || !exp_type)\n+\t\treturn 0\n+\tif(!job_is_xp_locked(src.title))\n+\t\treturn 0\n+\tif(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, C.mob))\n+\t\treturn 0\n+\tvar/isexempt = C.prefs.db_flags & DB_FLAG_EXEMPT\n+\tif(isexempt)\n+\t\treturn 0\n+\tvar/my_exp = calc_exp_type(C,get_exp_req_type())\n+\tvar/job_requirement = get_exp_req_amount()\n+\tif(my_exp >= job_requirement)\n+\t\treturn 0\n+\telse\n+\t\treturn (job_requirement - my_exp)\n+\n+/datum/job/proc/get_exp_req_amount()\n+\tif(title in GLOB.command_positions)\n+\t\tif(config.use_exp_restrictions_heads_hours)\n+\t\t\treturn config.use_exp_restrictions_heads_hours * 60\n+\treturn exp_requirements\n+\n+/datum/job/proc/get_exp_req_type()\n+\tif(title in GLOB.command_positions)\n+\t\tif(config.use_exp_restrictions_heads_department && exp_type_department)\n+\t\t\treturn exp_type_department\n+\treturn exp_type\n+\n+/proc/job_is_xp_locked(jobtitle)\n+\tif(!config.use_exp_restrictions_heads && jobtitle in GLOB.command_positions)\n+\t\treturn FALSE\n+\tif(!config.use_exp_restrictions_other && !(jobtitle in GLOB.command_positions))\n+\t\treturn FALSE\n+\treturn TRUE\n+\n+/proc/calc_exp_type(client/C,exptype)\n+\tvar/list/explist = C.prefs.exp.Copy()\n+\tvar/amount = 0\n+\tvar/list/typelist = GLOB.exp_jobsmap[exptype]\n+\tif(!typelist)\n+\t\treturn -1\n+\tfor(var/job in typelist[\"titles\"])\n+\t\tif(job in explist)\n+\t\t\tamount += explist[job]\n+\treturn amount\n+\n+/client/proc/get_exp_report()\n+\tif(!config.use_exp_tracking)\n+\t\treturn \"Tracking is disabled in the server configuration file.\"\n+\tvar/list/play_records = prefs.exp\n+\tif(!play_records.len)\n+\t\tset_exp_from_db()\n+\t\tplay_records = prefs.exp\n+\t\tif(!play_records.len)\n+\t\t\treturn \"[key] has no records.\"\n+\tvar/return_text = list()\n+\treturn_text += \"<UL>\"\n+\tvar/list/exp_data = list()\n+\tfor(var/category in SSjob.name_occupations)\n+\t\tif(play_records[category])\n+\t\t\texp_data[category] = text2num(play_records[category])\n+\t\telse\n+\t\t\texp_data[category] = 0\n+\tfor(var/category in GLOB.exp_specialmap)\n+\t\tif(play_records[category])\n+\t\t\texp_data[category] = text2num(play_records[category])\n+\t\telse\n+\t\t\texp_data[category] = 0\n+\tif(prefs.db_flags & DB_FLAG_EXEMPT)\n+\t\treturn_text += \"<LI>Exempt (all jobs auto-unlocked)</LI>\"\n+\n+\tfor(var/dep in exp_data)\n+\t\tif(exp_data[dep] > 0)\n+\t\t\tif(exp_data[EXP_TYPE_LIVING] > 0)\n+\t\t\t\tvar/percentage = num2text(round(exp_data[dep]/exp_data[EXP_TYPE_LIVING]*100))\n+\t\t\t\treturn_text += \"<LI>[dep] [get_exp_format(exp_data[dep])] ([percentage]%)</LI>\"\n+\t\t\telse\n+\t\t\t\treturn_text += \"<LI>[dep] [get_exp_format(exp_data[dep])] </LI>\"\n+\tif(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, mob))\n+\t\treturn_text += \"<LI>Admin (all jobs auto-unlocked)</LI>\"\n+\treturn_text += \"</UL>\"\n+\tvar/list/jobs_locked = list()\n+\tvar/list/jobs_unlocked = list()\n+\tfor(var/datum/job/job in SSjob.occupations)\n+\t\tif(job.exp_requirements && job.exp_type)\n+\t\t\tif(!job_is_xp_locked(job.title))\n+\t\t\t\tcontinue\n+\t\t\telse if(!job.required_playtime_remaining(mob.client))\n+\t\t\t\tjobs_unlocked += job.title\n+\t\t\telse\n+\t\t\t\tvar/xp_req = job.get_exp_req_amount()\n+\t\t\t\tjobs_locked += \"[job.title] [get_exp_format(text2num(calc_exp_type(src,job.get_exp_req_type())))] / [get_exp_format(xp_req)] as [job.get_exp_req_type()])\"\n+\tif(jobs_unlocked.len)\n+\t\treturn_text += \"<BR><BR>Jobs Unlocked:<UL><LI>\"\n+\t\treturn_text += jobs_unlocked.Join(\"</LI><LI>\")\n+\t\treturn_text += \"</LI></UL>\"\n+\tif(jobs_locked.len)\n+\t\treturn_text += \"<BR><BR>Jobs Not Unlocked:<UL><LI>\"\n+\t\treturn_text += jobs_locked.Join(\"</LI><LI>\")\n+\t\treturn_text += \"</LI></UL>\"\n+\treturn return_text\n+\n+\n+/client/proc/get_exp_living()\n+\tif(!prefs.exp)\n+\t\treturn \"No data\"\n+\tvar/exp_living = text2num(prefs.exp[EXP_TYPE_LIVING])\n+\treturn get_exp_format(exp_living)\n+\n+/proc/get_exp_format(expnum)\n+\tif(expnum > 60)\n+\t\treturn num2text(round(expnum / 60)) + \"h\"\n+\telse if(expnum > 0)\n+\t\treturn num2text(expnum) + \"m\"\n+\telse\n+\t\treturn \"0h\"\n+\n+/proc/update_exp(mins, ann = FALSE)\n+\tif(!SSdbcore.Connect())\n+\t\treturn -1\n+\tfor(var/client/L in GLOB.clients)\n+\t\tif(L.is_afk())\n+\t\t\tcontinue\n+\t\taddtimer(CALLBACK(L,/client/proc/update_exp_list,mins,ann),10)\n+\t\tCHECK_TICK\n+\n+/proc/update_exp_db()\n+\tSSdbcore.MassInsert(format_table_name(\"role_time\"),GLOB.exp_to_update,TRUE)\n+\tLAZYCLEARLIST(GLOB.exp_to_update)\n+\n+//resets a client's exp to what was in the db.\n+/client/proc/set_exp_from_db()\n+\tif(!src ||!ckey || !config.use_exp_tracking)\n+\t\treturn\n+\tif(!SSdbcore.Connect())\n+\t\treturn -1\n+\tvar/datum/DBQuery/exp_read = SSdbcore.NewQuery(\"SELECT job, minutes FROM [format_table_name(\"role_time\")] WHERE ckey = '[sanitizeSQL(ckey)]'\")\n+\tif(!exp_read.Execute())\n+\t\tvar/err = exp_read.ErrorMsg()\n+\t\tlog_game(\"SQL ERROR during exp_update_client read. Error : \\[[err]\\]\\n\")\n+\t\tmessage_admins(\"SQL ERROR during exp_update_client read. Error : \\[[err]\\]\\n\")\n+\t\treturn\n+\tvar/list/play_records = list()\n+\twhile(exp_read.NextRow())\n+\t\tplay_records[exp_read.item[1]] = text2num(exp_read.item[2])\n+\n+\tfor(var/rtype in SSjob.name_occupations)\n+\t\tif(!play_records[rtype])\n+\t\t\tplay_records[rtype] = 0\n+\tfor(var/rtype in GLOB.exp_specialmap)\n+\t\tif(!play_records[rtype])\n+\t\t\tplay_records[rtype] = 0\n+\n+\tprefs.exp = play_records\n+\n+\n+//updates player db flags\n+/proc/update_flag_db(client/C, newflag, state = FALSE)\n+\n+\tif(!SSdbcore.Connect())\n+\t\treturn -1\n+\n+\tif(!set_db_player_flags(C))\n+\t\treturn -1\n+\n+\tvar/datum/DBQuery/flag_read = SSdbcore.NewQuery(\"SELECT flags FROM [format_table_name(\"player\")] WHERE ckey='[sanitizeSQL(C.ckey)]'\")\n+\n+\tif(!flag_read.Execute())\n+\t\tvar/err = flag_read.ErrorMsg()\n+\t\tlog_game(\"SQL ERROR during player flags read. Error : \\[[err]\\]\\n\")\n+\t\tmessage_admins(\"SQL ERROR during player flags read. Error : \\[[err]\\]\\n\")\n+\t\treturn\n+\n+\tvar/playerflags = null\n+\twhile(flag_read.NextRow())\n+\t\tplayerflags = text2num(flag_read.item[1])\n+\n+\tif((playerflags & newflag) && !state)\n+\t\tC.prefs.db_flags &= ~newflag\n+\telse\n+\t\tC.prefs.db_flags |= newflag\n+\n+\tvar/datum/DBQuery/flag_update = SSdbcore.NewQuery(\"UPDATE [format_table_name(\"player\")] SET flags = '[C.prefs.db_flags]' WHERE ckey='[sanitizeSQL(C.ckey)]'\")\n+\n+\n+\tif(!flag_update.Execute())\n+\t\tvar/err = flag_update.ErrorMsg()\n+\t\tlog_game(\"SQL ERROR during exp_exempt update. Error : \\[[err]\\]\\n\")\n+\t\tmessage_admins(\"SQL ERROR during exp_exempt update. Error : \\[[err]\\]\\n\")\n+\t\treturn\n+\n+/client/proc/update_exp_list(minutes, announce_changes = FALSE)\n+\tif(!src ||!ckey || !config.use_exp_tracking)\n+\t\treturn\n+\tif(!SSdbcore.Connect())\n+\t\treturn -1\n+\tvar/datum/DBQuery/exp_read = SSdbcore.NewQuery(\"SELECT job, minutes FROM [format_table_name(\"role_time\")] WHERE ckey = '[sanitizeSQL(ckey)]'\")\n+\tif(!exp_read.Execute())\n+\t\tvar/err = exp_read.ErrorMsg()\n+\t\tlog_game(\"SQL ERROR during exp_update_client read. Error : \\[[err]\\]\\n\")\n+\t\tmessage_admins(\"SQL ERROR during exp_update_client read. Error : \\[[err]\\]\\n\")\n+\t\treturn -1\n+\tvar/list/play_records = list()\n+\twhile(exp_read.NextRow())\n+\t\tplay_records[exp_read.item[1]] = text2num(exp_read.item[2])\n+\n+\tfor(var/rtype in SSjob.name_occupations)\n+\t\tif(!play_records[rtype])\n+\t\t\tplay_records[rtype] = 0\n+\tfor(var/rtype in GLOB.exp_specialmap)\n+\t\tif(!play_records[rtype])\n+\t\t\tplay_records[rtype] = 0\n+\tvar/list/old_records = play_records.Copy()\n+\tif(isliving(mob))\n+\t\tif(mob.stat != DEAD)\n+\t\t\tvar/rolefound = FALSE\n+\t\t\tplay_records[EXP_TYPE_LIVING] += minutes\n+\t\t\tif(announce_changes)\n+\t\t\t\tto_chat(mob,\"<span class='notice'>You got: [minutes] Living EXP!\")\n+\t\t\tif(mob.mind.assigned_role)\n+\t\t\t\tfor(var/job in SSjob.name_occupations)\n+\t\t\t\t\tif(mob.mind.assigned_role == job)\n+\t\t\t\t\t\trolefound = TRUE\n+\t\t\t\t\t\tplay_records[job] += minutes\n+\t\t\t\t\t\tif(announce_changes)\n+\t\t\t\t\t\t\tto_chat(mob,\"<span class='notice'>You got: [minutes] [job] EXP!\")\n+\t\t\t\tif(!rolefound)\n+\t\t\t\t\tfor(var/role in GLOB.exp_jobsmap[EXP_TYPE_SPECIAL])\n+\t\t\t\t\t\tif(mob.mind.assigned_role == role)\n+\t\t\t\t\t\t\trolefound = TRUE\n+\t\t\t\t\t\t\tplay_records[role] += minutes\n+\t\t\t\t\t\t\tif(announce_changes)\n+\t\t\t\t\t\t\t\tto_chat(mob,\"<span class='notice'>You got: [minutes] [role] EXP!\")\n+\t\t\t\tif(mob.mind.special_role && !mob.mind.var_edited)\n+\t\t\t\t\tplay_records[mob.mind.special_role] += minutes\n+\t\t\t\t\tif(announce_changes)\n+\t\t\t\t\t\tto_chat(mob,\"<span class='notice'>You got: [minutes] [mob.mind.special_role] EXP!\")\n+\t\t\tif(!rolefound)\n+\t\t\t\tplay_records[\"Unknown\"] += minutes\n+\t\telse\n+\t\t\tplay_records[EXP_TYPE_GHOST] += minutes\n+\t\t\tif(announce_changes)\n+\t\t\t\tto_chat(mob,\"<span class='notice'>You got: [minutes] Ghost EXP!\")\n+\telse if(isobserver(mob))\n+\t\tplay_records[EXP_TYPE_GHOST] += minutes\n+\t\tif(announce_changes)\n+\t\t\tto_chat(mob,\"<span class='notice'>You got: [minutes] Ghost EXP!\")\n+\telse if(minutes)\t//Let \"refresh\" checks go through\n+\t\treturn\n+\tprefs.exp = play_records\n+\n+\tfor(var/jtype in play_records)\n+\t\tif(play_records[jtype] != old_records[jtype])\n+\t\t\tLAZYINITLIST(GLOB.exp_to_update)\n+\t\t\tGLOB.exp_to_update.Add(list(list(\n+\t\t\t\t\"job\" = \"'[sanitizeSQL(jtype)]'\",\n+\t\t\t\t\"ckey\" = \"'[sanitizeSQL(ckey)]'\",\n+\t\t\t\t\"minutes\" = play_records[jtype])))\n+\taddtimer(CALLBACK(GLOBAL_PROC,.proc/update_exp_db),20,TIMER_OVERRIDE|TIMER_UNIQUE)\n+\n+\n+//ALWAYS call this at beginning to any proc touching player flags, or your database admin will probably be mad\n+/proc/set_db_player_flags(client/C)","path":"code/modules/jobs/job_exp.dm","position":319,"original_position":319,"commit_id":"85c3ed64f0291a80d8a14469199b689ab1a72638","original_commit_id":"85c3ed64f0291a80d8a14469199b689ab1a72638","user":{"login":"Cyberboss","id":8171642,"avatar_url":"https://avatars0.githubusercontent.com/u/8171642?v=3","gravatar_id":"","url":"https://api.github.com/users/Cyberboss","html_url":"https://github.com/Cyberboss","followers_url":"https://api.github.com/users/Cyberboss/followers","following_url":"https://api.github.com/users/Cyberboss/following{/other_user}","gists_url":"https://api.github.com/users/Cyberboss/gists{/gist_id}","starred_url":"https://api.github.com/users/Cyberboss/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Cyberboss/subscriptions","organizations_url":"https://api.github.com/users/Cyberboss/orgs","repos_url":"https://api.github.com/users/Cyberboss/repos","events_url":"https://api.github.com/users/Cyberboss/events{/privacy}","received_events_url":"https://api.github.com/users/Cyberboss/received_events","type":"User","site_admin":false},"body":"Make this a client proc","created_at":"2017-07-07T13:20:01Z","updated_at":"2017-07-07T13:38:51Z","html_url":"https://github.com/tgstation/tgstation/pull/29105#discussion_r126144200","pull_request_url":"https://api.github.com/repos/tgstation/tgstation/pulls/29105","_links":{"self":{"href":"https://api.github.com/repos/tgstation/tgstation/pulls/comments/126144200"},"html":{"href":"https://github.com/tgstation/tgstation/pull/29105#discussion_r126144200"},"pull_request":{"href":"https://api.github.com/repos/tgstation/tgstation/pulls/29105"}}},"pull_request":{"url":"https://api.github.com/repos/tgstation/tgstation/pulls/29105","id":129319628,"html_url":"https://github.com/tgstation/tgstation/pull/29105","diff_url":"https://github.com/tgstation/tgstation/pull/29105.diff","patch_url":"https://github.com/tgstation/tgstation/pull/29105.patch","issue_url":"https://api.github.com/repos/tgstation/tgstation/issues/29105","number":29105,"state":"open","locked":false,"title":"Adds tracking amount of time spent playing departments 2: The fall of the Assistants.","user":{"login":"Shadowlight213","id":9410002,"avatar_url":"https://avatars0.githubusercontent.com/u/9410002?v=3","gravatar_id":"","url":"https://api.github.com/users/Shadowlight213","html_url":"https://github.com/Shadowlight213","followers_url":"https://api.github.com/users/Shadowlight213/followers","following_url":"https://api.github.com/users/Shadowlight213/following{/other_user}","gists_url":"https://api.github.com/users/Shadowlight213/gists{/gist_id}","starred_url":"https://api.github.com/users/Shadowlight213/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shadowlight213/subscriptions","organizations_url":"https://api.github.com/users/Shadowlight213/orgs","repos_url":"https://api.github.com/users/Shadowlight213/repos","events_url":"https://api.github.com/users/Shadowlight213/events{/privacy}","received_events_url":"https://api.github.com/users/Shadowlight213/received_events","type":"User","site_admin":false},"body":"Previous pr #26878\r\nNow with 98% less assistant biased data!\r\nSince I added assigned_roles to ghost roles, this tracks those as well. It's also more tolerant of admin var editing, since any assigned_role not previously defined in EXP_TYPE_SPECIAL or in the jobs controller will be tracked as \"Unknown\". This should keep the counts and percentages accurate.\r\n@MrStonedOne the exempt exp type has been removed and replaced with a flag in the player table like you requested.\r\nAlso, probably if this gets merged for real, the exp table should be reset, to clear the bad data from before.\r\n\r\n:cl:\r\nexperiment: The amount of time spent playing, and jobs played are now tracked per player.\r\nexperiment: This tracking can be used as a requirement of playtime to unlock jobs.\r\n/:cl:\r\n","created_at":"2017-07-07T02:49:05Z","updated_at":"2017-07-07T13:38:53Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c79c6a7f53aa950411164ab4877b8e099c1c567f","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/tgstation/tgstation/pulls/29105/commits","review_comments_url":"https://api.github.com/repos/tgstation/tgstation/pulls/29105/comments","review_comment_url":"https://api.github.com/repos/tgstation/tgstation/pulls/comments{/number}","comments_url":"https://api.github.com/repos/tgstation/tgstation/issues/29105/comments","statuses_url":"https://api.github.com/repos/tgstation/tgstation/statuses/85c3ed64f0291a80d8a14469199b689ab1a72638","head":{"label":"Shadowlight213:playerexp","ref":"playerexp","sha":"85c3ed64f0291a80d8a14469199b689ab1a72638","user":{"login":"Shadowlight213","id":9410002,"avatar_url":"https://avatars0.githubusercontent.com/u/9410002?v=3","gravatar_id":"","url":"https://api.github.com/users/Shadowlight213","html_url":"https://github.com/Shadowlight213","followers_url":"https://api.github.com/users/Shadowlight213/followers","following_url":"https://api.github.com/users/Shadowlight213/following{/other_user}","gists_url":"https://api.github.com/users/Shadowlight213/gists{/gist_id}","starred_url":"https://api.github.com/users/Shadowlight213/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shadowlight213/subscriptions","organizations_url":"https://api.github.com/users/Shadowlight213/orgs","repos_url":"https://api.github.com/users/Shadowlight213/repos","events_url":"https://api.github.com/users/Shadowlight213/events{/privacy}","received_events_url":"https://api.github.com/users/Shadowlight213/received_events","type":"User","site_admin":false},"repo":{"id":32113084,"name":"-tg-station","full_name":"Shadowlight213/-tg-station","owner":{"login":"Shadowlight213","id":9410002,"avatar_url":"https://avatars0.githubusercontent.com/u/9410002?v=3","gravatar_id":"","url":"https://api.github.com/users/Shadowlight213","html_url":"https://github.com/Shadowlight213","followers_url":"https://api.github.com/users/Shadowlight213/followers","following_url":"https://api.github.com/users/Shadowlight213/following{/other_user}","gists_url":"https://api.github.com/users/Shadowlight213/gists{/gist_id}","starred_url":"https://api.github.com/users/Shadowlight213/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shadowlight213/subscriptions","organizations_url":"https://api.github.com/users/Shadowlight213/orgs","repos_url":"https://api.github.com/users/Shadowlight213/repos","events_url":"https://api.github.com/users/Shadowlight213/events{/privacy}","received_events_url":"https://api.github.com/users/Shadowlight213/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Shadowlight213/-tg-station","description":"/tg/'s SS13 branch","fork":true,"url":"https://api.github.com/repos/Shadowlight213/-tg-station","forks_url":"https://api.github.com/repos/Shadowlight213/-tg-station/forks","keys_url":"https://api.github.com/repos/Shadowlight213/-tg-station/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shadowlight213/-tg-station/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shadowlight213/-tg-station/teams","hooks_url":"https://api.github.com/repos/Shadowlight213/-tg-station/hooks","issue_events_url":"https://api.github.com/repos/Shadowlight213/-tg-station/issues/events{/number}","events_url":"https://api.github.com/repos/Shadowlight213/-tg-station/events","assignees_url":"https://api.github.com/repos/Shadowlight213/-tg-station/assignees{/user}","branches_url":"https://api.github.com/repos/Shadowlight213/-tg-station/branches{/branch}","tags_url":"https://api.github.com/repos/Shadowlight213/-tg-station/tags","blobs_url":"https://api.github.com/repos/Shadowlight213/-tg-station/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shadowlight213/-tg-station/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shadowlight213/-tg-station/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shadowlight213/-tg-station/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shadowlight213/-tg-station/statuses/{sha}","languages_url":"https://api.github.com/repos/Shadowlight213/-tg-station/languages","stargazers_url":"https://api.github.com/repos/Shadowlight213/-tg-station/stargazers","contributors_url":"https://api.github.com/repos/Shadowlight213/-tg-station/contributors","subscribers_url":"https://api.github.com/repos/Shadowlight213/-tg-station/subscribers","subscription_url":"https://api.github.com/repos/Shadowlight213/-tg-station/subscription","commits_url":"https://api.github.com/repos/Shadowlight213/-tg-station/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shadowlight213/-tg-station/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shadowlight213/-tg-station/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shadowlight213/-tg-station/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shadowlight213/-tg-station/contents/{+path}","compare_url":"https://api.github.com/repos/Shadowlight213/-tg-station/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shadowlight213/-tg-station/merges","archive_url":"https://api.github.com/repos/Shadowlight213/-tg-station/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shadowlight213/-tg-station/downloads","issues_url":"https://api.github.com/repos/Shadowlight213/-tg-station/issues{/number}","pulls_url":"https://api.github.com/repos/Shadowlight213/-tg-station/pulls{/number}","milestones_url":"https://api.github.com/repos/Shadowlight213/-tg-station/milestones{/number}","notifications_url":"https://api.github.com/repos/Shadowlight213/-tg-station/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shadowlight213/-tg-station/labels{/name}","releases_url":"https://api.github.com/repos/Shadowlight213/-tg-station/releases{/id}","deployments_url":"https://api.github.com/repos/Shadowlight213/-tg-station/deployments","created_at":"2015-03-13T01:10:41Z","updated_at":"2016-01-12T00:23:32Z","pushed_at":"2017-07-07T02:37:41Z","git_url":"git://github.com/Shadowlight213/-tg-station.git","ssh_url":"git@github.com:Shadowlight213/-tg-station.git","clone_url":"https://github.com/Shadowlight213/-tg-station.git","svn_url":"https://github.com/Shadowlight213/-tg-station","homepage":"http://www.tgstation13.org/","size":894538,"stargazers_count":0,"watchers_count":0,"language":"DM","has_issues":false,"has_projects":true,"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":"tgstation:master","ref":"master","sha":"61af168b9eb9a1feeafb202505e51443738d05c3","user":{"login":"tgstation","id":1363778,"avatar_url":"https://avatars1.githubusercontent.com/u/1363778?v=3","gravatar_id":"","url":"https://api.github.com/users/tgstation","html_url":"https://github.com/tgstation","followers_url":"https://api.github.com/users/tgstation/followers","following_url":"https://api.github.com/users/tgstation/following{/other_user}","gists_url":"https://api.github.com/users/tgstation/gists{/gist_id}","starred_url":"https://api.github.com/users/tgstation/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tgstation/subscriptions","organizations_url":"https://api.github.com/users/tgstation/orgs","repos_url":"https://api.github.com/users/tgstation/repos","events_url":"https://api.github.com/users/tgstation/events{/privacy}","received_events_url":"https://api.github.com/users/tgstation/received_events","type":"Organization","site_admin":false},"repo":{"id":3234987,"name":"tgstation","full_name":"tgstation/tgstation","owner":{"login":"tgstation","id":1363778,"avatar_url":"https://avatars1.githubusercontent.com/u/1363778?v=3","gravatar_id":"","url":"https://api.github.com/users/tgstation","html_url":"https://github.com/tgstation","followers_url":"https://api.github.com/users/tgstation/followers","following_url":"https://api.github.com/users/tgstation/following{/other_user}","gists_url":"https://api.github.com/users/tgstation/gists{/gist_id}","starred_url":"https://api.github.com/users/tgstation/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tgstation/subscriptions","organizations_url":"https://api.github.com/users/tgstation/orgs","repos_url":"https://api.github.com/users/tgstation/repos","events_url":"https://api.github.com/users/tgstation/events{/privacy}","received_events_url":"https://api.github.com/users/tgstation/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tgstation/tgstation","description":"the /tg/station branch of SS13","fork":false,"url":"https://api.github.com/repos/tgstation/tgstation","forks_url":"https://api.github.com/repos/tgstation/tgstation/forks","keys_url":"https://api.github.com/repos/tgstation/tgstation/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tgstation/tgstation/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tgstation/tgstation/teams","hooks_url":"https://api.github.com/repos/tgstation/tgstation/hooks","issue_events_url":"https://api.github.com/repos/tgstation/tgstation/issues/events{/number}","events_url":"https://api.github.com/repos/tgstation/tgstation/events","assignees_url":"https://api.github.com/repos/tgstation/tgstation/assignees{/user}","branches_url":"https://api.github.com/repos/tgstation/tgstation/branches{/branch}","tags_url":"https://api.github.com/repos/tgstation/tgstation/tags","blobs_url":"https://api.github.com/repos/tgstation/tgstation/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tgstation/tgstation/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tgstation/tgstation/git/refs{/sha}","trees_url":"https://api.github.com/repos/tgstation/tgstation/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tgstation/tgstation/statuses/{sha}","languages_url":"https://api.github.com/repos/tgstation/tgstation/languages","stargazers_url":"https://api.github.com/repos/tgstation/tgstation/stargazers","contributors_url":"https://api.github.com/repos/tgstation/tgstation/contributors","subscribers_url":"https://api.github.com/repos/tgstation/tgstation/subscribers","subscription_url":"https://api.github.com/repos/tgstation/tgstation/subscription","commits_url":"https://api.github.com/repos/tgstation/tgstation/commits{/sha}","git_commits_url":"https://api.github.com/repos/tgstation/tgstation/git/commits{/sha}","comments_url":"https://api.github.com/repos/tgstation/tgstation/comments{/number}","issue_comment_url":"https://api.github.com/repos/tgstation/tgstation/issues/comments{/number}","contents_url":"https://api.github.com/repos/tgstation/tgstation/contents/{+path}","compare_url":"https://api.github.com/repos/tgstation/tgstation/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tgstation/tgstation/merges","archive_url":"https://api.github.com/repos/tgstation/tgstation/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tgstation/tgstation/downloads","issues_url":"https://api.github.com/repos/tgstation/tgstation/issues{/number}","pulls_url":"https://api.github.com/repos/tgstation/tgstation/pulls{/number}","milestones_url":"https://api.github.com/repos/tgstation/tgstation/milestones{/number}","notifications_url":"https://api.github.com/repos/tgstation/tgstation/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tgstation/tgstation/labels{/name}","releases_url":"https://api.github.com/repos/tgstation/tgstation/releases{/id}","deployments_url":"https://api.github.com/repos/tgstation/tgstation/deployments","created_at":"2012-01-21T17:32:47Z","updated_at":"2017-06-24T21:44:05Z","pushed_at":"2017-07-07T13:18:57Z","git_url":"git://github.com/tgstation/tgstation.git","ssh_url":"git@github.com:tgstation/tgstation.git","clone_url":"https://github.com/tgstation/tgstation.git","svn_url":"https://github.com/tgstation/tgstation","homepage":"http://www.tgstation13.org/","size":893622,"stargazers_count":385,"watchers_count":385,"language":"DM","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1423,"mirror_url":null,"open_issues_count":1012,"forks":1423,"open_issues":1012,"watchers":385,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/tgstation/tgstation/pulls/29105"},"html":{"href":"https://github.com/tgstation/tgstation/pull/29105"},"issue":{"href":"https://api.github.com/repos/tgstation/tgstation/issues/29105"},"comments":{"href":"https://api.github.com/repos/tgstation/tgstation/issues/29105/comments"},"review_comments":{"href":"https://api.github.com/repos/tgstation/tgstation/pulls/29105/comments"},"review_comment":{"href":"https://api.github.com/repos/tgstation/tgstation/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/tgstation/tgstation/pulls/29105/commits"},"statuses":{"href":"https://api.github.com/repos/tgstation/tgstation/statuses/85c3ed64f0291a80d8a14469199b689ab1a72638"}}}}
{"actor":{"display_login":"Cyberboss"}}