/// <summary> /// 返回CF比赛Standing /// </summary> /// <param name="skip"></param> /// <param name="top"></param> /// <param name="HasVirtual"></param> /// <returns></returns> /// <exception cref="ContestTypeMismatchException"></exception> public List<CFStanding> GetCFStanding(int skip, int top, bool HasVirtual,bool HasNotSubmit) { if (Type != ContestType.CF) throw new ContestTypeMismatchException(); List<CFStanding> ret=new List<CFStanding>(); var Probs=Problems(); using (var db = new CHDB()) { var raw = db.GetCFStanding(ID, RelativeNow,skip, top, HasVirtual, HasNotSubmit).ToArray(); for (int i = 0; i < raw.Length; i += Probs.Count()) { var desp = new List<CFStanding.DescriptionClass>(); for (int jj = 0; jj < Probs.Count(); jj++) { int j = i + jj; desp.Add(new CFStanding.DescriptionClass() { _huntFailed=(int)raw[j].FailedHunt, _huntSuccessfully=(int)raw[j].SuccessfulHunt, ACTime=raw[j].ACTime, isAC=(bool)raw[j].IsAC, FailedTimes=(int)raw[j].FailedTimes, Rating=(int)raw[j].Rating }); } var entity = new CFStanding() { Description = desp, FailedHack = desp.Sum(x => x._huntFailed), SuccessHack = desp.Sum(x => x._huntSuccessfully), User = raw[i].User, TotalRating = desp.Sum(x => x.Rating), IsVirtual = raw[i].Type == (int)AttendType.Virtual }; entity.TotalRating = entity.TotalRating + 100 * entity.SuccessHack - 25 * entity.FailedHack; ret.Add(entity); } } return ret; }
void CalcRating(CONTEST con, CHDB db) { List<string> Rank = new List<string>(); List<int> Rating = new List<int>(); double[] exp; int probs; int[] dat1; int[] dat2; switch ((Contest.ContestType)con.Type) { case Contest.ContestType.OI: var tmp_oi = db.GetOIStanding(con.ID, DateTime.Now, 0, con.CONTEST_ATTEND.Count, false, false).ToArray(); dat1 = new int[con.CONTEST_ATTEND.Count + 100]; dat2 = new int[con.CONTEST_ATTEND.Count + 100]; probs = con.PROBLEMs.Count; for (int i = 0; i < tmp_oi.Length; i += probs) { Rank.Add(tmp_oi[i].User); int k = i / probs; dat1[k] = dat2[k] = 0; for (int j = i; j < i + probs; j++) { dat1[k] += tmp_oi[j].Score ?? 0; dat2[k] += tmp_oi[j].ExecuteTime ?? 0; } } break; case Contest.ContestType.CF: var tmp_cf = db.GetCFStanding(con.ID, DateTime.Now, 0, con.CONTEST_ATTEND.Count, false, false).ToArray(); dat1 = new int[con.CONTEST_ATTEND.Count + 100]; dat2 = new int[con.CONTEST_ATTEND.Count + 100]; probs = con.PROBLEMs.Count; for (int i = 0; i < tmp_cf.Length; i += probs) { Rank.Add(tmp_cf[i].User); int k = i / probs; dat1[k] = dat2[k] = 0; for (int j = i; j < i + probs; j++) { dat1[k] += (tmp_cf[j].Rating ?? 0) + (tmp_cf[j].SuccessfulHunt ?? 0) * 100 - (tmp_cf[j].FailedHunt ?? 0) * 25; } } break; case Contest.ContestType.ACM: var tmp_acm = db.GetACMStanding(con.ID, DateTime.Now, 0, con.CONTEST_ATTEND.Count, false, false).ToArray(); dat1 = new int[con.CONTEST_ATTEND.Count + 100]; dat2 = new int[con.CONTEST_ATTEND.Count + 100]; probs = con.PROBLEMs.Count; for (int i = 0; i < tmp_acm.Length; i += probs) { Rank.Add(tmp_acm[i].User); int k = i / probs; dat1[k] = dat2[k] = 0; for (int j = i; j < i + probs; j++) { dat1[k] += (tmp_acm[j].IsAC ?? false) ? 1 : 0; dat2[k] += (tmp_acm[j].ACTime ?? 0) + (tmp_acm[j].FailedTimes ?? 0) * 20; } } break; default: throw new NotImplementedException(); } foreach (var u in Rank) { var Rat = (from r in db.RATINGs where r.USER1.Name == u orderby r.CONTEST1.EndTime descending select r.Rating1).FirstOrDefault(); Rating.Add(Rat == 0 ? 1500 : Rat); } int n = Rank.Count; if (n < 1) return; int m = (n + 1) / 2; for (int i = 0, j; i < n; i = j) { for (j = i + 1; j < n && dat1[j] == dat1[i] && dat2[j] == dat2[i]; j++) ; for (int k = i; k < j; k++) dat1[k] = (i + j - 1) / 2; } exp = new double[n]; double mid = (double)Rating.Sum() / n; for (int i = 0; i < n / 2; i++) exp[i] = mid + (3000 - mid) / Math.Pow(m - 1, 3) * Math.Pow(m - i - 1, 3); exp[n / 2] = mid; for (int i = n / 2 + 1; i < n; i++) exp[i] = mid - mid / Math.Pow(n - m, 3) * Math.Pow(i + 1 - m, 3); int weight = con.Weight; for (int i = 0; i < n; i++) { Rating[i] += (int)Math.Round((exp[dat1[i]] - Rating[i]) * Math.Pow(n, 1.0 / 8.0) / weight); Rating[i] = Math.Max(Rating[i], 1); Rating[i] = Math.Min(Rating[i], 3000); } for (int i = 0; i < n; i++) { var name = Rank[i]; foreach (var u in (from u in db.USERs where u.Name == name select u)) { u.RATINGs.Add(new RATING() { CONTEST1 = con, Rating1 = Rating[i] }); } } }