* 28 June 2015: **Promotion to Lieutenant Commander** for PotW * 21 May 2015: **Contribution towards Lieutenant Commander** for DELPHI entry * 26 April 2015: **Promoted to Lieutenant** for PotW win * 29 March 2015: **Promoted to Lieutenant j.g.** for PotW win * 4 January 2015: **Promoted to Ensign** for PotW win ## Section that ought to be ignored. powt * Post of the week for blub """,(7, 2, 9)], [ """ """, None], [""" #### Service Record * 11 September 2016: **Post of the Week** * 28 December 2014: **Promoted to Lieutenant j.g.** for Post of the Week * 11 March 2013: **Commissioned at Ensign.** * Post of the week for this invalid line of a continued service record after a commmission. """, None] ] for testcase in testcases: ret = RankUtils.analyzeServiceRecord(testcase[0].split("\n")) print("Got \"{}\", expected \"{}\"".format(ret, testcase[1]))
def step2(self, state, input, subreddit): """Post of the Week Step 2 - Calculate Promotions""" if len(input) < 1 or len(input) > 2: state["error"] = "Your comment has a line number other than two or one. Please keep to the aforementioned syntax." return state if not input[0].lower().startswith("potw "): state["error"] = "Your comments first line must start with 'POTW '" return state potwIndices = input[0][len("POTW "):].split(" ") ecIndices = [] if len(input) == 2: if not input[1].lower().startswith("ec "): state["error"] = "Your comments second line must start with 'EC '" return state ecIndices = input[1][len("EC "):].split(" ") # important: user-facing indices are in [1,n+1], move them back to [0,n], also convert them to numbers try: potwIndices = [int(x)-1 for x in potwIndices] ecIndices = [int(x)-1 for x in ecIndices] # remove duplicates potwIndices = list(set(potwIndices)) ecIndices = list(set(ecIndices)) if any([x < 0 or x >= len(state["voteEntries"]) for x in potwIndices]): raise ValueError("") if any([x < 0 or x >= len(state["voteEntries"]) for x in ecIndices]): raise ValueError("") except: return {"error": "Some of the indices you provided were not numbers, or not within the required range."} if len(set(ecIndices) ^ set(potwIndices)) != len(ecIndices) + len(potwIndices): return {"error": "No post can win BOTH Exemplary Contribution and Post of the Week."} # Assemble the winners and candidates for the CPO position cpoCandidates = [] # list of (user, current_flair_css) winnersInfo = [] for idx,voteEntry in enumerate(state["voteEntries"]): # Do not check for winning-state in a misguided attempt at optimization here, need to go through it all to be # able to see if anyone's rank entitles them to a CPO promotion. winnerInfo = RedditUtils.findFirstLinkedObject(voteEntry.body, subreddit, self.r) if winnerInfo is None: state["error"] = "Couldn't find the thread/comment referenced by the vote entry {}\n\n".format(idx) return state linkText, linkURL, contributionObject = winnerInfo # get the user from the vote comment match = re.search(r'\/u\/(.*?)\s', voteEntry.body, re.IGNORECASE) if match is None: state["error"] = "Couldn't find the username from the vote comment for '{}'\n\n".format(voteEntry.body) return state # ensure that they are both the same username = match.group(1).strip() if contributionObject.author is None or username.lower() != contributionObject.author.name.lower(): state["error"] = ("Username in the voting thread doesn't match the username of the nominated object." + " Username: {}, Nominated Object: {}").format(username, idx) return state winnerUser = contributionObject.author # returns dict {"flair_css_class":?, "flair_text":?, "user":?} winnerFlair = self.r.get_flair(subreddit, winnerUser) winnerCurrentRank = RankUtils.getRankLevelFromFlair(winnerFlair["flair_css_class"]) # cpo possible at all? if winnerCurrentRank in RankUtils.cpoStepRanks: cpoCandidates.append((winnerUser, winnerFlair["flair_css_class"] if winnerFlair["flair_css_class"] is not None else "")) logging.info("CPO Candidate: " + winnerUser.name) if not idx in potwIndices+ecIndices: continue logging.info("{} - {} - {}".format(winnerUser.name, winnerCurrentRank, RankUtils.rankLevels[winnerCurrentRank]["name"])) winnersInfo.append({"user": winnerUser, "currentRank": winnerCurrentRank, "promotionKind": "potw" if idx in potwIndices else "ec", "comment": voteEntry, "text": winnerInfo[0]}) notes = "" message = "" finalWinnerInfo = [] # now that we have all the winners, lets see who gets promoted to what for wi in winnersInfo: # calculate the promotion of that person, to that end get his service # record username = wi["user"].name careerPotW = 0 careerDelphi = 0 total = 0 serviceRecord = self.r.get_wiki_page(subreddit, username) # check if the record exists. This combersome way currently seems to be # the only working one pageExists = False try: serviceRecord.content_md pageExists = True except: pageExists = False temporaryNoPromotion = False if serviceRecord is None or pageExists is False: if wi["currentRank"] >= RankUtils.serviceRecordThresholdRank: # Ensign ought to have a page ... notes += "* Person /u/{} ought to have a service record, but hasn't gotten one. Setting them to not promoted temporarily, **please review and, if applicable, change this**.\n".format(username) temporaryNoPromotion = True else: # split into lines lines = serviceRecord.content_md.split("\n") ret = RankUtils.analyzeServiceRecord(lines) if ret is None: notes += "* Couldn't read the [service record](https://reddit.com/r/DaystromInstitute/wiki/{}) of user /u/{}. Setting them to not promoted temporarily, **please review and, if applicable, change this**.\n".format(username, username) temporaryNoPromotion = True else: careerPotW, careerDelphi, total = ret logging.info("Analyzed the service record of /u/{}. They have {} PotW, {} DELPHI totalling {}".format(username, careerPotW, careerDelphi, total)) # check the next promotion total += 1 # if they were promoted careerPotW += 1 resDict = {"serviceRecord": serviceRecord, "user": wi["user"], "currentRank": RankUtils.rankLevels[wi["currentRank"]], "promotionKind": wi["promotionKind"], "comment": wi["comment"], "text": wi["text"]} res = None newRank = wi["currentRank"] if temporaryNoPromotion: res = (False, "") elif wi["currentRank"] < 3: # crewman, cpo and citizen get autopromoted to ensign on PotW res = (True, "") newRank = RankUtils.stepFinishRank # ensign elif wi["currentRank"] < len(RankUtils.rankLevels) - 1: nextRank = RankUtils.rankLevels[wi["currentRank"] + 1] res = nextRank["advanceFunction"](total, careerPotW, careerDelphi) newRank = newRank + 1 else: res = (False, "") resDict["willBePromoted"] = res[0] resDict["promoteAftermessage"] = res[1] resDict["promoteTo"] = RankUtils.rankLevels[newRank] finalWinnerInfo.append(resDict) # format this for the message message += "\n\n" message += formatFinalWinnerInfo(finalWinnerInfo) message += "\nPlease note: \n\n" message += notes message += "\n" + InfoMessages.step2 self.messageHandler.dispatchOutput(message) # put it into the state state["finalWinnerInfo"] = finalWinnerInfo state["cpoCandidates"] = cpoCandidates state["reminders"].append(notes) return state