user generated / user specific functions - php

I'm looking for the most elegant and secure method to do the following.
I have a calendar, and groups of users.
Users can add events to specific days on the calendar, and specify how long each event lasts for.
I've had a few requests from users to add the ability for them to define that events of a specific length include a break, of a certain amount of time, or require that a specific amount of time be left between events.
For example, if event is >2 hours, include a 20min break. for each event, require 30 minutes before start of next event.
The same group that has asked for an event of >2 hours to include a 20 min break, could also require that an event >3 hours include a 30 minute break.
In the end, what the users are trying to get is an elapsed time excluding breaks calculated for them. Currently I provide them a total elapsed time, but they are looking for a running time.
However, each of these requests is different for each group. Where one group may want a 30 minute break during a 2 hour event, and another may want only 10 minutes for each 3 hour event.
I was kinda thinking I could write the functions into a php file per group, and then include that file and do the calculations via php and then return a calculated total to the user, but something about that doesn't sit right with me.
Another option is to output the groups functions to javascript, and have it run client-side, as I'm already returning the duration of the event, but where the user is part of more than one group with different rules, this seems like it could get rather messy.
I currently store the start and end time in the database, but no 'durations', and I don't think I should be storing the calculated totals in the db, because if a group decides to change their calculations, I'd need to change it throughout the db.
Is there a better way of doing this?
I would just store the variables in mysql, but I don't see how I can then say to mysql to calculate based on those variables.
I'm REALLY lost here. Any suggestions? I'm hoping somebody has done something similar and can provide some insight into the best direction.
If it helps, my table contains
eventid, user, group, startDate, startTime, endDate, endTime, type
The json for the event which I return to the user is
{"eventid":"'.$eventId.'", "user":"'.$userId.'","group":"'.$groupId.'","type":"'.$type.'","startDate":".$startDate.'","startTime":"'.$startTime.'","endDate":"'.$endDate.'","endTime":"'.$endTime.'","durationLength":"'.$duration.'", "durationHrs":"'.$durationHrs.'"}
where for example, duration length is 2.5 and duration hours is 2:30.

Store only the start time and end time for the event, and a BLOB field named notes.
I've worked on several systems that suffered from feature creep of these sorts of requirements until the code and data modeling became nothing but an unmaintainable collection of exception cases. It was a lot of work to add new permutations to the code, and typically these cases were used only once.
If you need enforcement of the rules and conditions described in the notes field, it's actually more cost-effective to hire an event coordinator instead of trying to automate everything in software. A detail-oriented human can adapt to the exception cases much more rapidly than you can adapt the code to handle them.

Related

Writing for holes in ranges

I'm trying to write a program that relies on date ranges. I am trying to be able to alert users when there are holes in their ranges but I need a reliable way to find those, and to be able to handle them effectively.
My solution was to change any dates so that any day inserted into the app is rewritten so it is that day at noon. Here is the code for that:
public function reformDate($date){
return strtotime(date("F j, Y", $date)." 12:00pm");
}
This would allow me to deal with a more regular and consistent dataset. Because I only had to see how many days they were apart, rather than seeing how many seconds they were apart and making a decision whether that time quantity represented an intentional gap or not...
I saw, however, when you put something in for today at noon, then if you put something tomorrow at noon, since the values are the same, and based on my restriction:
Select * from times where :date between start and end
It triggers a response. My solution for this was to just add one to the start variable, and detract one from the end variable, so I can easily check if there are overlap by asking if the difference between the start of one and end of another is more than 2.
Anyway, my question is: is this a good way to do this? I'm particularly worried about the number 2 - do I need to worry about using such small units of time (that is unix time, by the way). Alternately, should I create a test that if two time units overlap perfectly - they should be accepted?

Start a php code (competition in which some users are) for users, logged in or not

Ok I know the title doesn't really tell you what my problem is but I'll try it now.
I am developing a game. People can subscribe their animals for a race. That race starts at a specific time. It is a race for which ALL users can subscribe. So the calculation of which animal is first, second etc. happens in an php file that is executed, every 2mins there is a new calculation for about 1h. So there are 30 calculations. But ofc. this code is not connected to the logged in user. The logged in user can click on the LIVE button to see the current result.
Example: There is a race at 17.00 later today. 15 animals subscribed, from 4 players and they can all check how their animals are doing.
I do not want someone to post me the full code but I want to know how I should let a php code run for about 1 hour (so execute code, sleep 2min, new calculation, sleep 2min and so on) on my server or so. So it is not connected to the user.
I thought about cron jobs but that is really not the solution for this I believe.
Thank you for reading :p
Two approaches:
You use an algorithm which will always come to the same conclusion, regardless of when it is run and who runs it. You just define the starting parameters, then at any time you can calculate the result (or the intermediate result at any point in time between start and finish) when needed. So any user can at any time visit your site and the algorithm will calculate the current standings on the fly from some fixed starting condition.
Alternatively, you keep all data in a central data store and actually update the data in certain intervals; any user can request the current standings at any time and the latest data from the datastore will be used. You will still need an algorithm that has traits of the one described above, since you're likely explicitly not actually running the simulation in real time. Just every x seconds, you run your calculations again, calculating what is supposed to have changed from the last time you ran them.
In essence, any algorithm you use needs this approach. Even a "realtime" program simply keeps looping, changing values little by little from their previous state. The interval between theses changes can be arbitrarily stretched out, to the point where you calculate nothing until it becomes necessary. In the meantime, you just store all the data you need in a database.
Cron jobs are the wright way i think. Check this out when you are not so good with algorithm:How To: PHP with Cron job Maybe you have to use different cron jobs.

php/mysql - i am doing a web app that has 'achievements' (a bit like xbox achievements) - whats the best way to program this?

i am going to have achievements such as
get 1000 points
login 20 times
complete 2 tasks within 24 hrs
etc
what is the best way to program this? (like, the logic behind it. it would be a wast eof reseouces to check every possible achievement on every page load)
This is a fairly open-ended question. One approach is to store progress for what users have already achieved in a database table (one column for each achievement) and every time progress is made, up the progress value. A magic value for each achievement (null, 1 million, whatever) can be set when the target is reached and then you just need to check which columns in each user's entry have the magic value.
You could just store the progress and calculate the achievement status on each access, but I think that would be problematic for things like the time-limited tasks you mention and people might get irked if you change the goals for any reason and they lose achievements they had previously gained.
An arguably more correct approach would be to have a static "Achievements" table in which each row details one achievement, along with the goals. You'd then have a separate "Progress" table in which each user would have a row for every different achievement they are working towards. This is more work to implement, but will allow you to add / remove / alter goals much more easily at a later date than hard-coding them to column names in your progress table. I don't think you should underestimate the value this will give you later on. This way, the progress table can have multiple columns for each user / achievement combination, which allows you to store things like time achievement reached etc. and you can very simply get a list of achievements like this:
SELECT achievement_id
FROM progress
WHERE user_id = $user
AND achievment_time IS NOT NULL
You've got to check something for each page load if you want to display achievements on each page, but if you record progress in one of these ways, you're not going back to first principles and calculating how many logins have been made, how many tasks have been completed, etc. every time - just a SELECT from your DB, which I assume is what you mean.
Recording progress is simple for things like number of logins (just increment a counter each time they perform the action), but you'll obviously have to think a bit more carefully about the logic for keeping tabs on progress for time-limited achievements. Here, you'll need to keep track of timestamps for when actions were performed in a separate table (you may already be doing this, of course) and each time a new timestamp is created, count those in the preceding time period to see if the achievement has been reached.

best strategy for timing out a transaction/session?

I'm working on a web application that automates a reservation process using the Google Calendar API and PHP. When the user first selects a date, my script creates a "tentative" event on the Calendar to prevent other users from trying to select the same date. However, to avoid the proliferation of tentative dates created by users that don't follow through, I want to impose a time limit on the transaction process, so that if the user leaves the app or takes too long, the tentative date will be removed from the calendar (and thus available for other users to reserve).
We're currently storing the appointments in a MySQL db as well as the Google Cal, so here's my current strategy: when the tentative appointment is first created, store the tentative appointment in the db with a timestamp. Then, schedule a cron job (maybe every hour or so) that scans through the database and removes tentative reservations based on the age of their timestamp (removing them from both the db and the google cal).
In theory, this should work. However, my question is this: is there a simpler/more elegant way to do this that I'm not thinking of? Does anyone have a better solution to this problem?
Not sure if this is "better", but if the primary goal is limiting clutter you could cap the number of tentative events during a given time period and have your cron job delete all but the newest N during each period. This way the calendar can't get choked if you have a sudden rush of tentative events, but you can keep them around longer when there's less activity giving people a larger window to confirm their reservation during slow periods.
When someone tries to create an appointment at the same time as a tentative appointment, check to see if the tentative appointment is "too old". If it is: delete it and create the new one. If it isn't: tell the user an appointment is already being created at that time.

How to handle dates that repeat indefinitely

I am implementing a fairly simple calendar on a website using PHP and MySQL. I want to be able to handle dates that repeat indefinitely and am not sure of the best way to do it.
For a time limited repeating event it seems to make sense to just add each event within the timeframe into my db table and group them with some form of recursion id.
But when there is no limit to how often the event repeats, is it better to
a) put records in the db for a specific time frame (eg the next 2 years) and then periodically check and add new records as time goes by - The problem with this is that if someone is looking 3 years ahead, the event won't show up
b) not actually have records for each event but instead when i check in my php code for events within a specified time period, calculate wether a repeated event will occur within this time period - The problem with this is that it means there isn't a specific record for each event which i can see being a pain when i then want to associate other info (attendance etc) with that event. It also seems like it might be a bit slow
Has anyone tried either of these methods? If so how did it work out? Or is there some other ingenious crafty method i'm missing?
I'd take approach b and if someone adds something to it, I'd create a "real" event entry.
Edit:
How many periodic events do you expect and what kind of periodic events would that be? (eg: every monday, every two weeks etc.)
I would create a single record for a repeated event. Then in case more info has to be added to a specific date, I would create a record for the attachment with a reference to the repeated event.
Third vote for option B - rationale being that the data should only ever be queried for a limited timeframe (i.e. start and end). For performance reasons I'd suggest that, in addition to storing the date/time of the first occurrence, number of occurrences and frequency that you also maintain the last occurrence in the database.
C.
From my experience, generating recurring dates and checking if a specific date is in that pattern isn't all that bad performance-wise. There's only 365 days in a year. 10,000 days is already almost 30 years. which means, the size of the input/output is relatively small in a practical scenario.
This library may help (but it's javascript): http://github.com/mooman/recurring_dates

Categories