-
Notifications
You must be signed in to change notification settings - Fork 8
Add feature to manage random-set contest #197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: tnfsh
Are you sure you want to change the base?
Conversation
Without pro_sets, it is hard to do many operations. Such as generate pro_set list for manage UI.
The value of param has been checked at handler. We don't need to check twice.
Because the RequestHandler instance of each request is independent, the contest is always consistent with the database. This means db is the only thing must be updated.
Because ip is default to 0.0.0.0, the ip_range of contest can't be None.
Order is a keyword in SQL.
This reverts commit 78d86f1. Because of the redis cache, the contest is also need to be update to set redis cache.
Both add_pro_set & update_ip need to append a random problem to the ip_pro_list, but only add_pro_set need to update pro_list & do some check, so I let this logic be a single function.
If there are no ip in the db, there will be no item in ip_pro_list and , as a result, get 0 pro_set count. Use sql to get count of distinct order is a more stable way.
| async def add_random_pro(self, contest: Contest, pro_set: list[int]): | ||
| ''' | ||
| Append a random problem in pro_set to each ip's problem list | ||
| ''' | ||
| pro_size = len(pro_set) | ||
| if pro_size == 1: | ||
| for pro_list in contest.ip_pro_list.values(): | ||
| pro_list.append(pro_set[0]) | ||
| elif pro_size == 2: | ||
| for pro_list in contest.ip_pro_list.values(): | ||
| pro_list.append(pro_set[random.randint(0, 1)]) | ||
| else: | ||
| idx = 0 | ||
| for pro_list in contest.ip_pro_list.values(): | ||
| idx = (idx + random.randint(1,pro_size-1)) % pro_size | ||
| pro_list.append(pro_set[idx]) | ||
|
|
||
| async with self.db.acquire() as con: | ||
| # Insert por_id into contest_ip_joints | ||
| await con.executemany( | ||
| ''' | ||
| INSERT INTO contest_ip_joints ("contest_id", "ip", "pro_id") | ||
| VALUES ($1, $2, $3) | ||
| ''', | ||
| [(contest.contest_id, str(ip), pro_list[-1]) for ip, pro_list in contest.ip_pro_list.items()] | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the main algorithm to assign problems to contestants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So how should I get all problems from a single account?
By passing account ip address?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't implement that feature.
Should I create a page that contains the table showing the pro_ids assigned to each IP address?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not UI.
We need an interface internally to handle this, because most of the functions only have access to the Account or acct_id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I understood.
Yes, caller should passing account's IP address to get all problems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But, I haven't implement get_problems function.
I plan to implement that function when I am completing the user-side features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
Current swapRow direct change innerHTML, this will cause event listener failed.
index.reload() will not refresh full page.
Description
TOJ will be used as an online judge for exams.
To avoiding cheating, we introduced a new "Random Set" contest mode in this PR.
In this contest mode, each problem number corresponds to a problem set.
And if a problem set contains more than 2 problems, any adjacent contestants will always see different problems. Otherwise, the assignment is randomized.
Implementation
contest_ip_jointsis added to record the problems assign to the ip.start_ipandend_ipare added to tableconteststo record the contests' ip range.Note
This PR only completes the admin-side features, user-side features like scoreboard will be done later.