/**
* This is the system for case control. It keeps tracks of all the current
* open cases in the area and any modifications that are done to them.
* @author Pinkfish
* @started Tue Jul 11 18:09:01 PDT 2000
*/
#define NOMIC_SYSTEM_NO_CLASSES
#define NOMIC_SYSTEM_CASE_CLASSES
#include <nomic_system.h>
private mapping _open_cases;
private mapping _recently_closed_cases;
private mapping _closed_cases;
private int _next_case_id;
private int _next_note_id;
void save_me();
void send_council_inform(string area, int only_magistrates,
string mess);
void create() {
_open_cases = ([ ]);
_closed_cases = ([ ]);
_recently_closed_cases = ([ ]);
_next_case_id = 1;
_next_note_id = 1;
} /* create() */
/**
* This method creates an area.
* @param area the name of the area to create
*/
void create_area(string area) {
if (_open_cases[area]) {
return ;
}
_open_cases[area] = ({ });
_closed_cases[area] = ({ });
_recently_closed_cases[area] = ({ });
} /* create_area() */
/**
* This returns the cases which are currently open.
* @param area the are to get the cases in
* @return the list of opened cases
*/
int* query_open_cases(string area) {
return _open_cases[area];
} /* query_open_cases() */
/**
* This method returns the cases which are currently closed.
* @param area the area to get the cases in
* @return the list of closed cases
*/
int* query_closed_cases(string area) {
return _closed_cases[area];
} /* query_closed_cases() */
/**
* This method returns the set of recently closed cases. These are
* cases that can be appealed.
* @param area the area to get the cases in
* @return the list of recently closed cases
*/
int* query_recently_closed_cases(string area) {
return _recently_closed_cases[area];
} /* query_recently_closed_cases() */
/**
* This method returns the file name for the case given the id.
* @param id the id to return
* @return the file name
*/
string query_case_file_name(int id) {
return NOMIC_CASE_SAVE + sprintf("cases/%02d/%d_case", id % 20, id);
} /* query_case_file_name() */
/**
* This method finds the next case id.
* @return the next case id
*/
int query_next_case_id() {
int next;
do {
next = _next_case_id++;
} while (sizeof(stat(query_case_file_name(next))));
return next;
} /* query_next_case_id() */
private void save_case(class nomic_case stuff) {
string fname;
string tmp;
fname = query_case_file_name(stuff->id);
tmp = save_variable(stuff);
unguarded((: write_file($(fname), $(tmp), 1) :));
} /* save_case() */
/**
* This method returns the file name for the note given the id.
* @param id the id to return
* @return the file name
*/
string query_note_file_name(int id) {
return NOMIC_CASE_SAVE + sprintf("notes/%02d/%d_note", id % 20, id);
} /* query_note_file_name() */
/**
* This method finds the next note id.
* @return the next note id
*/
int query_next_note_id() {
int next;
do {
next = _next_note_id++;
} while (sizeof(stat(query_note_file_name(next))));
return next;
} /* query_next_note_id() */
private void save_note(class nomic_case_note stuff) {
string fname;
string tmp;
fname = query_note_file_name(stuff->id);
tmp = save_variable(stuff);
unguarded((: write_file($(fname), $(tmp) ) :));
} /* save_note() */
private int create_case(string opener, string short, string* people) {
class nomic_case new_case;
new_case = new(class nomic_case);
new_case->id = query_next_case_id();
new_case->opener = opener;
new_case->short = short;
new_case->people = people;
new_case->notes = ({ });
new_case->events = ({ });
new_case->time_opened = time();
save_case(new_case);
return new_case->id;
} /* create_case() */
private int create_note(string person, string text) {
class nomic_case_note new_note;
new_note = new(class nomic_case_note);
new_note->id = query_next_note_id();
new_note->person = person;
new_note->text = text;
new_note->time_created = time();
save_note(new_note);
return new_note->id;
} /* create_note() */
private class nomic_case_event create_event(int type, string person,
string mess, mixed data) {
class nomic_case_event event;
event = new(class nomic_case_event);
event->type = type;
event->mess = mess;
event->person = person;
event->event_time = time();
event->data = data;
return event;
} /* create_event() */
/**
* This method returns the short name of the event type.
* @param type the type to find the name of
* @return the name of the type
*/
string query_event_name(int type) {
switch (type) {
case NOMIC_CASE_EVENT_CLOSE :
return "closed case";
case NOMIC_CASE_EVENT_APPEAL :
return "appealed case";
case NOMIC_CASE_EVENT_ADD_PERSON :
return "add person";
case NOMIC_CASE_EVENT_REMOVE_PERSON :
return "remove person";
default :
return "unknown";
}
} /* query_event_name() */
/**
* This method returns the case associated with the specified open
* case.
* @param area the area to look for the case in
* @param id the id of the case
* @return the case class
*/
class nomic_case query_open_case(string area, int id) {
string fname;
string tmp;
if (!_open_cases[area]) {
return 0;
}
if (member_array(id, _open_cases[area]) == -1) {
return 0;
}
fname = query_case_file_name(id);
tmp = unguarded((: read_file($(fname)) :));
if (tmp) {
return restore_variable(tmp);
}
return 0;
} /* query_open_case() */
/**
* This method returns the case associated with the specified recently
* closed case.
* @param area the area to look for the case in
* @param id the id of the case
* @return the case class
*/
class nomic_case query_recently_closed_case(string area, int id) {
string fname;
string tmp;
if (!_recently_closed_cases[area]) {
return 0;
}
if (member_array(id, _recently_closed_cases[area]) == -1) {
return 0;
}
fname = query_case_file_name(id);
tmp = unguarded((: read_file($(fname)) :));
if (tmp) {
return restore_variable(tmp);
}
return 0;
} /* query_closed_case() */
/**
* This method returns the case associated with the specified closed
* case.
* @param area the area to look for the case in
* @param id the id of the case
* @return the case class
*/
class nomic_case query_closed_case(string area, int id) {
string fname;
string tmp;
if (!_closed_cases[area]) {
return 0;
}
if (member_array(id, _closed_cases[area]) == -1) {
return 0;
}
fname = query_case_file_name(id);
tmp = unguarded((: read_file($(fname)) :));
if (tmp) {
return restore_variable(tmp);
}
return 0;
} /* query_closed_case() */
/**
* This method return the exciting note associated with the case.
* @param note_num the number of the note
* @return the note class, or 0 on failure
*/
class nomic_case_note query_note(int note_num) {
string fname;
string tmp;
fname = query_note_file_name(note_num);
tmp = unguarded((: read_file($(fname)) :));
if (tmp) {
return restore_variable(tmp);
}
return 0;
} /* query_note() */
/**
* This method opens a new case.
* @param area the area the case is in
* @param opener the person who opened it
* @param short the short description of the case
* @param people the people involved
* @return 0 on failure and teh case id on success
*/
int add_new_case(string area, string opener, string short, string* people) {
int case_id;
if (!_open_cases[area]) {
return 0;
}
case_id = create_case(opener, short, people);
_open_cases[area] += ({ case_id });
save_me();
send_council_inform(area, 1, opener + " opened a case with " +
query_multiple_short(people));
return case_id;
} /* add_new_case() */
/**
* This method closes the case.
* @param area the area the case is in
* @param id the id of the case to close
* @param closer the person that closes the case
* @param result the string saying what the result of the case is
* @param desc the description of the close reason
* @param data special internal data used specifically for appeals
* @return 1 on success, 0 on failure
*/
int close_case(string area, int id, string closer, string result,
mixed data) {
class nomic_case the_case;
class nomic_case_event event;
the_case = query_open_case(area, id);
if (!the_case || !stringp(result)) {
return 0;
}
event = create_event(NOMIC_CASE_EVENT_CLOSE, closer, result, data);
the_case->events += ({ event });
save_case(the_case);
_open_cases[area] -= ({ the_case->id });
_recently_closed_cases[area] += ({ the_case->id });
save_me();
send_council_inform(area, 1, closer + " closed a case with " +
query_multiple_short(the_case->people));
return 1;
} /* close_case() */
/**
* This method sets the case as reopened for an appeal. After an appeal
* the case will be closed again.
* @param area the area the case is in
* @param id the of the case to appeal
* @param appealer the person who does the appeal
* @param reason the reason for the appeal
* @return 1 on success, 0 on failure
*/
int appeal_case(string area, int id, string appealer, string reason) {
class nomic_case the_case;
class nomic_case_event event;
the_case = query_recently_closed_case(area, id);
if (!the_case || !stringp(reason)) {
return 0;
}
event = create_event(NOMIC_CASE_EVENT_APPEAL, appealer, reason, 0);
the_case->events += ({ event });
save_case(the_case);
_recently_closed_cases[area] -= ({ the_case->id });
_open_cases[area] += ({ the_case->id });
save_me();
send_council_inform(area, 1, appealer + " appeals a case with " +
query_multiple_short(the_case->people));
return 1;
} /* appeal_case() */
/**
* This method adds a note to the case.
* @param area the area to get the case in
* @param id the id of the case
* @param person the person adding the note
* @param text the actual note text
* @return 1 on success, 0 on failure
*/
int add_note_to_case(string area, int id, string person, string text) {
class nomic_case the_case;
int note_id;
the_case = query_open_case(area, id);
if (!the_case) {
return 0;
}
note_id = create_note(person, text);
the_case->notes += ({ note_id });
save_case(the_case);
save_me();
return 1;
} /* add_note_to_case() */
/**
* This method adds a person to the case.
* @param area the area the case is in
* @param id the id of the case
* @param adder the person that adds the person
* @param person the person to be added to the case
* @param text the reason for adding the person
* @return 1 on success, 0 on failure
*/
int add_person_to_case(string area, int id, string adder,
string person, string text) {
class nomic_case the_case;
class nomic_case_event event;
the_case = query_open_case(area, id);
if (!the_case || !stringp(text) ||
member_array(person, the_case->people) != -1) {
return 0;
}
event = create_event(NOMIC_CASE_EVENT_ADD_PERSON, adder, text, 0);
the_case->events += ({ event });
the_case->people += ({ person });
save_case(the_case);
return 1;
} /* add_person_to_case() */
/**
* This method removes a person from the case.
* @param area the area the case is in
* @param id the id of the case
* @param remover the person that removes the person
* @param person the person to be removed to the case
* @param text the reason for removeing the person
* @return 1 on success, 0 on failure
*/
int remove_person_from_case(string area, int id, string remover,
string person, string text) {
class nomic_case the_case;
class nomic_case_event event;
the_case = query_open_case(area, id);
if (!the_case || !stringp(text) ||
member_array(person, the_case->people) == -1) {
return 0;
}
event = create_event(NOMIC_CASE_EVENT_REMOVE_PERSON, remover, text, 0);
the_case->events += ({ event });
the_case->people -= ({ person });
save_case(the_case);
return 1;
} /* remove_person_to_case() */
/**
* This method goes through and checks the recently closed cases to see
* if any of them need to be moved to the closed set.
*/
void update_recently_closed_cases() {
string area;
int* stuff;
int id;
class nomic_case the_case;
class nomic_case_event event;
int last_close;
foreach (area, stuff in _recently_closed_cases) {
foreach (id in stuff) {
the_case = query_recently_closed_case(area, id);
last_close = 0;
foreach (event in the_case->events) {
if (event->type == NOMIC_CASE_EVENT_CLOSE) {
last_close = event->event_time;
}
}
if (last_close < time() - NOMIC_CASE_APPEAL_TIME) {
//
// Ok, move the case into the really closed bunch.
//
_closed_cases[area] += ({ id });
_recently_closed_cases[area] -= ({ id });
}
}
}
} /* update_recently_closed_cases() */