public static async Task<GenderizeResult> GenderizeName(string name, string country) { // if there's a cached entry for this first name and country, return it if (Cache.ContainsKey(name + "_" + country)) { if (Cache[name + "_" + country] == null) return null; // well, return it only if it meets the confidence and count requirements if((Cache[name + "_" + country].Probability>=ProbabilityThreshold)&&(Cache[name + "_" + country].Count>=CountThreshold)) return Cache[name + "_" + country]; } else { HttpClient client = new HttpClient(); // query the API to infer gender from the first name AND the country of the user string query = string.Format("https://api.genderize.io/?name={0}&country_id={1}{2}", name, country, (ApiKey != String.Empty) ? "&apikey=" + ApiKey : string.Empty); var response = client.GetAsync(query).Result; if (response.IsSuccessStatusCode) { JObject jo = JObject.Parse(await response.Content.ReadAsStringAsync()); // if the gender proerty comes back as null, it's possible that there are no entries for that name in the specified country // let's try to infer the gender from the first name alone, then if ((string)jo["gender"] == null) { query = string.Format("https://api.genderize.io/?name={0}{1}", name, (ApiKey != String.Empty) ? "&apikey=" + ApiKey : string.Empty); response = client.GetAsync(query).Result; jo = JObject.Parse(await response.Content.ReadAsStringAsync()); } // if we did get a gender inference if ((string)jo["gender"] != null) { GenderizeResult gr = new GenderizeResult { Name = (string)jo["name"], Gender = (string)jo["gender"], Probability = (float)jo["probability"], Count = (int)jo["count"] }; // cache the result Cache.Add(name + "_" + country, gr); // if the confidence meets the thresholds, return the GenderizeResult if ((gr.Probability >= ProbabilityThreshold) && (gr.Count >= CountThreshold)) return gr; } else { // the name was not present at all in the API. // add placeholder in cache, so we don't keep calling the API needlessly for this name/country combination Cache.Add(name + "_" + country, null); } } } return null; }
// infers the gender of the current user, then recursely infers the gender mix for all of his/her reports // populated the Reports collection in the process // same note about 1 hour execution limit applies here public async void GetGenderMix(string accessToken) { Males = Females = Undefined = Contacts = 0; // infer account's gender GenderData = await GenderizeProxy.GenderizeName(FirstName, Country); // if we could not establish the user's gender if (GenderData == null) { Undefined = 1; } else { // we have a successful inference. The account is the first entry for his/her own org if (GenderData.Gender == "male") { Males = 1; } else { Females = 1; } } // retrieve all the direct reports of the current account string[] upnComponents = UPN.Split('@'); string alias = upnComponents[0]; string domain = upnComponents[1]; string reportsQuery = String.Format("https://graph.windows.net/{0}/users/{1}/directReports?api-version=1.6", domain, UPN); HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); HttpResponseMessage response = httpClient.GetAsync(reportsQuery).Result; if (response.IsSuccessStatusCode) { string rez = response.Content.ReadAsStringAsync().Result; JObject jo = JObject.Parse(rez); // if the account does have reports foreach (JObject jreport in jo["value"]) { if ((string)jreport["userPrincipalName"] != null) { // create an account representing the report Account report = new Account { UPN = (string)jreport["userPrincipalName"], FirstName = (string)jreport["givenName"], Country = InferCountryFromPhoneNumber((string)jreport["telephoneNumber"]), Reports = new List<Account>() }; // recurse on it report.GetGenderMix(accessToken); // fold back into the tally the gender numbers of the sub org Males += report.Males; Females += report.Females; Undefined += report.Undefined; Contacts += report.Contacts; // append the Account represeting the report to the Reports collection Reports.Add(report); } // no UPN means that the accunt is not a User, but a Contact. We don't count those here. else Contacts += 1; } } if (Reports.Count != 0) Console.WriteLine(" {0}'s org - {1} males, {2} females, {3} indetermined", UPN, Males, Females, Undefined); }