blob: da1a7e24628d5aabd7c36ec68575157b249edd63 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/* /obj/toostels/fehlerteufel.c
2 Fehlerteufel - Magiertool zur Abfrage des Fehler-Daemons der Mudlib
3 Autor: Zesstra
4 Changelog:
5*/
6
7#pragma strict_types
8#pragma pedantic
9#pragma range_check
10#pragma no_shadow
11#pragma no_inherit
12
13inherit "/std/secure_thing";
14inherit "/secure/errord-structs";
15
16#include <defines.h>
17#include <wizlevels.h>
18#include <properties.h>
19#include <moving.h>
20#include <errord.h>
21#include <config.h>
22#include <debug_info.h>
23#include <input_to.h>
24#include <strings.h>
25
26#define TI this_interactive()
27
28#define DEBUG(x) if (funcall(symbol_function('find_player),"zesstra"))\
29 tell_object(funcall(symbol_function('find_player),"zesstra"),\
30 "EDBG: "+x+"\n")
31
32// variables
33private string owner; // UID vom Eigentuemer
34private string *uids=({}); // UIDs, auf die man schreibrechte hat
35private string *filteruids=({}); // wenn nicht-leer, nur diese UIDs zeigen
36private string *monitoruids=({}); // diese UIDs in die Liste einschliessen
37private int filterstatus=0; // Filter an oder aus?
38private mapping issuelist = ([]);
39/* ([ type1: ([uid1: <issuelist>, uid2: <issuelist> ]),
40 type2: ... ])
41 <issuelist> ist ein < <int|string>* >* vom ErrorD */
42
43//Welche Art von Fehler anzeigen?
44private int modus=T_RTERROR | T_RTWARN | T_REPORTED_ERR;
45private string *xmonitoruids = ({}); // expanded Monitor-UIDs
46private int lfehler; // letzter 'benutzter' Fehler.
47private int fehlerzahl; // fehlerzahl im letzten Reset.
48private mapping feingabe; // gerade eingegebener Fehler
49
50// ************** private functions **************
51private varargs int get_issuelist(int lmodus);
52private void get_uids();
53
54// irgendeinen Fehler oder Warnung anzeigen.
55private int show_entry(struct fullissue_s issue)
56{
57 if (!issue) return 0;
58
59 string txt=ERRORD->format_error(issue, 0);
60
61 if (!stringp(txt) || !sizeof(txt))
62 return 0;
63
64 tell_object(PL,txt+"\n");
65 return 1;
66}
67
68protected int _feingabe_fertig(string arg) {
69
70 if (arg == "j")
71 {
72 if (!feingabe[F_MSG])
73 {
74 tell_object(PL,
75 "Also, eine Fehlerbeschreibung solltest Du schon eingeben! Abgebrochen.\n");
76 }
77 else
78 {
79 string hashkey = (string)ERRORD->LogReportedError(feingabe);
80 tell_object(PL, sprintf(
81 "Vielen Dank! Die ID des eingegebenen Fehlers lautet: %s\n",
82 hashkey || "N/A"));
83 }
84 }
85 else
86 {
87 tell_object(PL, "Fehlereingabe abgebrochen.\n");
88 }
89
90 feingabe = 0;
91
92 return 1;
93}
94
95public int CmdFehlerEingabe(string arg) {
Arathorn2e77c0a2016-08-27 14:37:47 +020096 object|string target;
MG Mud User88f12472016-06-24 23:31:02 +020097
98 if (feingabe)
99 {
Arathorn2e77c0a2016-08-27 14:37:47 +0200100 tell_object(PL, "Du gibst doch bereits einen Fehler ein!\n");
MG Mud User88f12472016-06-24 23:31:02 +0200101 return 1;
102 }
103 feingabe = ([]);
104
105 if (arg)
106 {
107 target = present(arg);
108 if (!target)
109 target = find_object(arg); // vielleicht direkt angegeben?
Arathorn2e77c0a2016-08-27 14:37:47 +0200110 // Vielleicht gibt es ja eine Datei, die so heisst?
111 if (!target && file_size(arg) >= 0)
112 target = arg;
MG Mud User88f12472016-06-24 23:31:02 +0200113 }
114 // wenn nix gefunden, Environment des Magiers nehmen.
115 if (!target)
Arathorn2e77c0a2016-08-27 14:37:47 +0200116 {
117 tell_object(PL, break_string("Kein Objekt und keine Datei "
118 "angegeben, Fehler wird fuer den Raum eingetragen.",78));
MG Mud User88f12472016-06-24 23:31:02 +0200119 target = environment(environment());
Arathorn2e77c0a2016-08-27 14:37:47 +0200120 }
MG Mud User88f12472016-06-24 23:31:02 +0200121
122 feingabe[F_OBJ] = target;
123
124 tell_object(PL, break_string(sprintf(
125 "Du beginnst einen Fehlereintrag fuer das Objekt: %O\n", target),78));
126
127 input_to(function void (string str)
128 {
129 if (sizeof(str)) feingabe[F_MSG] = str;
130 }, INPUT_PROMPT, "Fehlerbeschreibung eingeben:\n");
131
132 input_to(function void (string str)
133 {
134 if (sizeof(str)) feingabe[F_PROG] = str;
135 else feingabe[F_PROG] = "unbekannt";
136 }, INPUT_PROMPT|INPUT_APPEND,
137 "Programm eingeben, in dem der Fehler auftritt (falls bekannt):\n");
138
139 input_to(function void (string str)
140 {
141 if (sizeof(str)) feingabe[F_LINE] = to_int(str);
142 tell_object(PL,break_string(sprintf(
143 "Du hast die folgenden Daten eingegeben:\n"
144 "Objekt: %O\n"
145 "Fehlerbeschreibung: %s\n"
146 "Programm: %s\n"
147 "Zeilennr.: %d\n",
148 feingabe[F_OBJ], feingabe[F_MSG] || "", feingabe[F_PROG],
149 feingabe[F_LINE]), 78, "", BS_LEAVE_MY_LFS));
150 }, INPUT_PROMPT|INPUT_APPEND,
151 "Zeilennr. eingeben, in der der Fehler auftritt (falls bekannt):\n");
152
153 input_to(#'_feingabe_fertig,
154 INPUT_PROMPT|INPUT_APPEND, "Eingaben korrekt? (j/n)\n");
155
156 return 1;
157}
158
159public int CmdFehlerZeigen(string arg)
160{
161 int issueid;
162
163 if (stringp(arg) && sizeof(arg))
164 {
165 arg = trim(arg, TRIM_BOTH);
166 issueid = to_int(arg);
167 }
168 else
169 {
170 issueid = lfehler;
171 arg = to_string(issueid);
172 }
173 notify_fail("Einen Eintrag mit dieser ID gibt es nicht!\n");
174
175 // Mit einem / am Anfang ist arg wohl ein Filename, wenn to_string(issueid)
176 // == arg wird die Issueid von oben genommen.
177 struct fullissue_s issue;
178 struct fullissue_s *issues;
179 if (arg[0] == '/')
180 {
181 issues=({});
182 foreach(int m: ALL_ERR_TYPES)
183 {
184 if (!(m & modus))
185 continue;
186 struct fullissue_s *tmp =
187 (struct fullissue_s *)ERRORD->QueryIssuesByFile(arg, m);
188 if (tmp)
189 issues+=tmp;
190 }
191 if (!sizeof(issues))
192 issues=0;
193 }
194 else if (to_string(issueid) == arg)
195 issue = (struct fullissue_s)ERRORD->QueryIssueByID(issueid);
196 else
197 issue = (struct fullissue_s)ERRORD->QueryIssueByHash(arg);
198
199 if (structp(issue))
200 {
201 show_entry(issue);
202 // letzten Fehler merken.
203 lfehler = issueid;
204 return 1;
205 }
206 // Wenn das nicht erfolgreich ist, ist das Argument evtl. ein Objekt-,
207 // Programm- oder Ladename. In dem Fall alle von denen anzeigen, die passen
208 // hierbei wird der Typ NICHT beruecksichtigt.
209 else if (pointerp(issues))
210 {
211 foreach(issue : issues)
212 {
213 show_entry(issue);
214 }
215 return 1;
216 }
217
218 notify_fail("Keine Eintraege fuer diesen Dateinamen/diese ID gefunden.\n");
219 return 0;
220}
221
222// Loescht alle Fehler und Warnungen eines Objekts (soweit per modus
223// ausgewaehlt). Entscheidend ist der _Loadname_!
224private int DeleteErrorsForLoadname(string loadname)
225{
226 int sum_deleted;
227 // Bei == 0 wird sonst alles geloescht. ;-)
228 if (!loadname)
229 return 0;
230
231 foreach(int m: ALL_ERR_TYPES)
232 {
233 if (!(m & modus))
234 continue;
235 < <int|string>* >* list = ERRORD->QueryIssueListByLoadname(loadname,m);
236 if (pointerp(list))
237 {
238 foreach(<int|string>* row : list)
239 {
240 if ((int)ERRORD->ToggleDeleteError(row[0]) == 1)
241 {
242 tell_object(PL,
243 row[0] + " als geloescht markiert.\n");
244 }
245 }
246 sum_deleted+=sizeof(list);
247 }
248 }
249 return sum_deleted;
250}
251
252public int CmdFehlerLoeschen(string arg)
253{
254 int issueid;
255 arg = (string)this_player()->_unparsed_args(0);
256
257 if (stringp(arg) && sizeof(arg))
258 issueid = to_int(arg);
259 else
260 issueid = lfehler;
261
262 notify_fail("Einen Eintrag mit dieser ID/diesem Loadname gibt es nicht!\n");
263
264 int res = (int)ERRORD->ToggleDeleteError(issueid);
265 if (res == 1)
266 {
267 tell_object(PL,
268 "Fehler/Warnung wurde zum Loeschen markiert und wird in Kuerze "
269 "geloescht.\n");
270 lfehler = issueid;
271 return 1;
272 }
273 else if (res==0)
274 {
275 tell_object(PL,"Loeschmarkierung wurde entfernt.\n");
276 lfehler = issueid;
277 return 1;
278 }
279 else if (res < -1)
280 {
281 tell_object(PL, "Irgendwas ist beim Loeschen schiefgegangen. "
282 "Keine Schreibrechte?\n");
283 lfehler = issueid;
284 return 1;
285 }
286 // res war == -1 -> Fehler nicht gefunden. Vielleicht ist es nen Loadname
287 return DeleteErrorsForLoadname(arg);
288}
289
290public int CmdRefresh(string arg) {
291 reset();
292 tell_object(PL,"Fehlerdaten wurden neu eingelesen.\n");
293 return 1;
294}
295
296private int select_modus(string arg) {
297 int lmodus;
298 switch(arg) {
299 case "alles":
300 case "alle":
301 lmodus = T_RTERROR | T_RTWARN | T_CTERROR | T_CTWARN | T_REPORTED_ERR
302 | T_REPORTED_IDEA | T_REPORTED_TYPO | T_REPORTED_MD;
303 break;
304 case "fehler":
305 case "error":
306 case "errors":
307 lmodus=T_RTERROR | T_CTERROR | T_REPORTED_ERR;
308 break;
309 case "warnungen":
310 case "warnung":
311 case "warning":
312 case "warnings":
313 lmodus=T_RTWARN | T_CTWARN;
314 break;
315 case "laufzeitfehler":
316 lmodus=T_RTERROR;
317 break;
318 case "ladezeitfehler":
319 lmodus=T_CTERROR;
320 break;
321 case "fehlerhinweis":
322 case "fehlerhinweise":
323 case "hinweise":
324 lmodus=T_REPORTED_ERR;
325 break;
326 case "ideen":
327 case "idee":
328 lmodus=T_REPORTED_IDEA;
329 break;
330 case "md":
331 lmodus=T_REPORTED_MD;
332 break;
333 case "typo":
334 case "typos":
335 lmodus=T_REPORTED_TYPO;
336 break;
337 case "laufzeitwarnungen":
338 case "runtimewarnings":
339 lmodus=T_RTWARN;
340 break;
341 case "ladezeitwarnungen":
342 case "compiletimewarnings":
343 lmodus=T_CTWARN;
344 break;
345 default:
346 lmodus=modus;
347 }
348 return lmodus;
349}
350
351private string * errorlabel(int t)
352{
353 switch(t) {
354 case T_RTERROR:
355 return ({"Laufzeitfehler","Laufzeitfehler","Dieser Laufzeitfehler"});
356 case T_REPORTED_ERR:
357 return ({"Fehlerhinweis","Fehlerhinweise","Dieser Fehlerhinweis"});
358 case T_REPORTED_IDEA:
359 return ({"Idee","Ideen","Diese Idee"});
360 case T_REPORTED_MD:
361 return ({"fehlende Detail","fehlende Details","Dieses fehlende Detail"});
362 case T_REPORTED_TYPO:
363 return ({"Typo","Typos","Dieser Typo"});
364 case T_RTWARN:
365 return ({"Laufzeitwarnung","Laufzeitwarnungen","Diese Laufzeitwarnung"});
366 case T_CTWARN:
367 return ({"Ladezeitwarnung", "Ladezeitwarnungen","Diese Ladezeitwarnung"});
368 case T_CTERROR:
369 return ({"Ladezeitfehler","Ladezeitfehler","Dieser Ladezeitfehler"});
370 }
371 raise_error("Unkannter Fehlertyp: "+t+"\n");
372 return 0;
373}
374
375public int CmdFehlerListe(string arg) {
376 string txt;
377 //string *luids;
378 int lmodus; // modus fuer diese Liste
379 mapping fehlerbackup;
380
381 if (stringp(arg) && sizeof(arg))
382 {
383 lmodus=select_modus(arg);
384 if (lmodus != modus)
385 {
386 fehlerbackup=issuelist; // Fehlerliste von 'modus' aufheben
387 get_issuelist(lmodus); // neue Fehlerliste holen
388 }
389 }
390 else
391 lmodus=modus;
392/*
393 if (!fehlerzahl)
394 {
395 txt="Fuer Deine UIDs sind keine Fehler/Warnungen bekannt. :-)\n";
396 tell_object(PL,txt);
397 return 1;
398 }
399*/
400 foreach(int typ, mapping typemap : issuelist)
401 {
402 if (!(typ & lmodus))
403 continue; // Type nicht gewaehlt.
404 txt="";
405 if (!sizeof(typemap)) {
406 tell_object(PL,
407 "Es sind keine " + errorlabel(typ)[1] + "Deiner UIDs bekannt. :-)");
408 continue;
409 }
410 foreach(string uid, < <int|string>* >* list : typemap)
411 {
412 if (!sizeof(list)) continue;
413 if (filterstatus && member(filteruids, uid) > -1) continue;
414 //txt+=sprintf("%s:\n", uid);
415 foreach(<int|string>* row : list)
416 {
417 txt+=sprintf("%:6d | %:40-s | %:26-s\n",
418 row[0], row[1], row[2]);
419 }
420 }
421 if (txt && sizeof(txt))
422 {
423 txt = sprintf("\nFuer Deine UIDs sind folgende %s bekannt (Filter: %s):\n"
424 "%:6|s | %:40|s | %s\n",
425 errorlabel(typ)[1], (filterstatus ? "an" : "aus"),
426 "ID", "Loadname", "UID")
427 + txt;
428 tell_object(PL, txt);
429 }
430 else
431 {
432 tell_object(PL, sprintf(
433 "\nFuer Deine UIDs sind keine %s bekannt (Filter: %s):\n",
434 errorlabel(typ)[1], (filterstatus ? "an" : "aus")));
435 }
436 }
437
438 if (mappingp(fehlerbackup) && modus!=lmodus)
439 issuelist=fehlerbackup; // fehlerliste fuer 'modus' restaurieren
440 return 1;
441}
442
443public int CmdFilter(string arg) {
444
445 arg=(string)PL->_unparsed_args(0);
446
447 if (!stringp(arg) || !sizeof(arg)) {
448 tell_object(PL,break_string(
449 "Momentan interessieren Dich folgende UIDs nicht"
450 +(filterstatus ? " (Filter an):\n" : " (Filter aus):\n")
451 +CountUp(filteruids)+"\n", 78,"",BS_LEAVE_MY_LFS));
452 return 1;
453 }
454
455 if (arg=="keine") {
456 filteruids=({});
457 filterstatus=1;
458 tell_object(PL,break_string(
459 "Dein Fehlerteufel wird Dir nun nur noch ausgewaehlte "
460 "Fehler berichten. Momentan hast Du keine UIDs ausgeblendet. "
461 "(Filter an)",78));
462 }
463 else if (arg=="alle") {
464 filterstatus=1;
465 filteruids=uids;
466 tell_object(PL,break_string(
467 "Dein Fehlerteufel wird Dir nun nur noch ausgewaehlte "
468 "Fehler berichten. Du blendest momentan alle UIDs aus. "
469 "(Filter an)",78));
470 }
471 else if (arg=="aus") {
472 filterstatus=0;
473 tell_object(PL,break_string(
474 "Dein Fehlerteufel wird Dir nun wieder alle Fehler berichten. ",
475 78));
476 }
477 else if (arg=="an" || arg=="ein") {
478 filterstatus=1;
479 tell_object(PL,break_string(
480 "Dein Fehlerteufel wird Dir nun nur noch ausgewaehlte "
481 "Fehler berichten.",78));
482 }
483 else {
484 foreach(string uid: explode(arg," ")-({""})) {
485 if (sizeof(uid)>1 && uid[0]=='+') {
486 if (member(filteruids,uid[1..])==-1)
487 filteruids+=({uid[1..]});
488 }
489 else if (sizeof(uid)>1 && uid[0]=='-') {
490 filteruids-=({uid[1..]});
491 }
492 else {
493 if (member(filteruids,uid)==-1)
494 filteruids+=({uid});
495 else
496 filteruids-=({uid});
497 }
498 }
499 }
500
501 tell_object(PL,break_string(
502 "Momentan interessieren Dich folgende UIDs nicht"
503 +(filterstatus ? " (Filter an):\n" : " (Filter aus):\n")
504 +CountUp(filteruids)+"\n", 78,"",BS_LEAVE_MY_LFS));
505
506 return 1;
507}
508
509public int CmdMonitor(string arg) {
510
511 arg=(string)PL->_unparsed_args(0);
512
513 if (!stringp(arg) || !sizeof(arg)) {
514 tell_object(PL,break_string(
515 "Momentan interessieren Dich folgende UIDs zusaetzlich zu Deinen: \n"
516 +(sizeof(monitoruids) ? CountUp(monitoruids) : "")
517 +"\n", 78,"",BS_LEAVE_MY_LFS));
518 return 1;
519 }
520
521 if (arg=="keine") {
522 monitoruids=({});
523 xmonitoruids=({});
524 tell_object(PL,break_string(
525 "Dein Fehlerteufel wird Dir nun nur noch "
526 "Fehler Deiner eigenen UIDs berichten.",78));
527 return 1;
528 }
529 else {
530 foreach(string uid: explode(arg," ")-({""})) {
531 if (sizeof(uid)>1 && uid[0]=='+') {
532 if (member(monitoruids,uid[1..])==-1)
533 monitoruids+=({uid[1..]});
534 }
535 else if (sizeof(uid)>1 && uid[0]=='-') {
536 monitoruids-=({uid[1..]});
537 }
538 else {
539 if (member(monitoruids,uid)==-1)
540 monitoruids+=({uid});
541 else
542 monitoruids-=({uid});
543 }
544 }
545 }
546 get_uids();
547 tell_object(PL,break_string(
548 "Momentan interessieren Dich folgende UIDs zusaetzlich zu Deinen: \n"
549 +(sizeof(monitoruids) ? CountUp(monitoruids) : "")
550 +"\n", 78,"",BS_LEAVE_MY_LFS));
551
552 return 1;
553}
554
555public int CmdModus(string arg) {
556 string txt;
557
558 // Argument verwursten
559 if (stringp(arg) && sizeof(arg)) {
560 modus = select_modus(arg);
561 reset(); // neue Fehlerliste holen
562 }
563 // aktuelle Einstellung ausgeben.
564 string *modstr=({});
565 if (modus & T_RTERROR)
566 modstr+=({"Fehler (Laufzeit)"});
567 if (modus & T_RTWARN)
568 modstr+=({"Warnungen (Laufzeit)"});
569 if (modus & T_CTERROR)
570 modstr+=({"Fehler (Ladezeit)"});
571 if (modus & T_CTWARN)
572 modstr+=({"Warnungen (Ladezeit)"});
573 if (modus & T_REPORTED_ERR)
574 modstr+=({"Fehlerhinweise"});
575 if (modus & T_REPORTED_IDEA)
576 modstr+=({"Idee"});
577 if (modus & T_REPORTED_MD)
578 modstr+=({"fehlende Details"});
579 if (modus & T_REPORTED_TYPO)
580 modstr+=({"Typo"});
581
582 tell_object(PL, break_string(
583 "Dein Fehlerteufel wird Dir nun ueber aufgetretene "
584 +CountUp(modstr)+" Bericht erstatten.",78));
585 return(1);
586}
587
588int CmdAddNote(string str) {
589 string *arr;
590
591 notify_fail("Bitte eine ID und einen Text angeben!\n");
592 if(!objectp(TI))
593 return 0;
594
595 str=(string)PL->_unparsed_args(0);
596 if (!stringp(str) || !sizeof(str))
597 return 0;
598
599 arr=explode(str," ")-({""});
600 if (sizeof(arr)<2)
601 return 0;
602 int issueid = to_int(arr[0]);
603
604 str=implode(arr[1..]," "); //text wiederherstellen, aber ohne ID
605
606 switch((int)ERRORD->AddNote(issueid,str))
607 {
608 case -1:
609 tell_object(PL,
610 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
611 return 1;
612 case -3:
613 return 0; //offenbar keine Notiz angegeben.
614 }
615 // letzten Fehler merken.
616 lfehler = issueid;
617
618 tell_object(PL,
619 sprintf("Deine Notiz wurde zu %d hinzugefuegt.\n",
620 issueid));
621 return 1;
622}
623
624int CmdFix(string str)
625{
626 string *arr;
627 int fixing, res;
628
629 notify_fail("Bitte eine ID und optional eine Notiz angeben!\n");
630 if(!objectp(TI))
631 return 0;
632
633 str=(string)PL->_unparsed_args(0);
634 if (!stringp(str) || !sizeof(str))
635 return 0;
636
637 arr=explode(str," ")-({""});
638 if (!sizeof(arr))
639 return 0;
640
641 int issueid=to_int(arr[0]);
642 if (sizeof(arr)>1)
643 str=implode(arr[1..]," "); //text wiederherstellen, aber ohne Key
644 else str=0;
645
646 if (query_verb()=="ffix" || query_verb()=="fehlerfix")
647 {
648 fixing=1;
649 res = (int)ERRORD->ResolveIssue(issueid, str);
650 }
651 else
652 {
653 res = (int)ERRORD->ReOpenIssue(issueid, str);
654 }
655
656 if (res==-1)
657 {
658 tell_object(PL,
659 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
660 }
661 else if (res==-10)
662 {
663 tell_object(PL,
664 "Du hast leider keinen Schreibzugriff diesen Fehler.\n"
665 "Aber vielleicht moechtest Du mit fnotiz eine Notiz anhaengen?\n");
666 }
667 else if (res==-3)
668 {
669 if (fixing)
670 tell_object(PL,"Dieser Fehler ist bereits gefixt.\n");
671 else
672 tell_object(PL,"Dieser Fehler ist noch nicht gefixt.\n");
673 }
674 else if (res==1)
675 {
676 tell_object(PL,
677 sprintf("Fehler %d als gefixt markiert.\n",issueid));
678 }
679 else if (res==0)
680 {
681 tell_object(PL,
682 sprintf("Fehler %d als nicht gefixt markiert.\n",issueid));
683 }
684 // letzten Fehler merken.
685 lfehler = issueid;
686
687 return 1;
688}
689
690int CmdLock(string str) {
691 string *arr;
692 int locking;
693 int res;
694
695 notify_fail("Bitte eine ID und optional eine Notiz angeben!\n");
696 if(!objectp(TI))
697 return 0;
698
699 str=(string)PL->_unparsed_args(0);
700 if (!stringp(str) || !sizeof(str))
701 return 0;
702
703 arr=explode(str," ")-({""});
704 if (!sizeof(arr))
705 return 0;
706
707 int issueid=to_int(arr[0]);
708 if (sizeof(arr)>1)
709 str=implode(arr[1..]," "); //text wiederherstellen, aber ohne Key
710 else str=0;
711
712 if (query_verb()=="flock" || query_verb()=="fehlerlock")
713 {
714 locking=1;
715 res=(int)ERRORD->LockIssue(issueid,str);
716 }
717 else
718 {
719 res=(int)ERRORD->UnlockIssue(issueid,str);
720 }
721
722 if (res==-1)
723 {
724 tell_object(PL,
725 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
726 }
727 else if (res==-10)
728 {
729 tell_object(PL,
730 "Du hast leider keinen Schreibzugriff diesen Fehler.\n");
731 }
732 else if (res==-3)
733 {
734 if (locking)
735 tell_object(PL,
736 "Dieser Fehler ist bereits vor autom. Loeschen geschuetzt.\n");
737 else
738 tell_object(PL,
739 "Dieser Fehler ist bereits zum autom. Loeschen freigegeben.\n");
740 }
741 else if (res==-2)
742 {
743 tell_object(PL,
744 "Dieser Fehler ist bereits gefixt und wird bald geloescht.\n");
745 }
746 else if (res==1)
747 {
748 tell_object(PL,
749 sprintf("Fehler %d vor autom. Loeschen geschuetzt.\n",issueid));
750 }
751 else if (res==0)
752 {
753 tell_object(PL,
754 sprintf("Fehler %d zum autom. Loeschen freigegeben.\n",issueid));
755 }
756 // letzten Fehler merken.
757 lfehler = issueid;
758
759 return 1;
760}
761
762int CmdReassign(string str) {
763
764 notify_fail("Bitte eine ID, die neue UID und ggf. eine Notiz angeben!\n");
765 if(!objectp(TI))
766 return 0;
767
768 str=(string)PL->_unparsed_args(0);
769 if (!stringp(str) || !sizeof(str))
770 return 0;
771
772 string *arr=explode(str," ")-({""});
773 if (sizeof(arr)<2)
774 return 0;
775 int issueid=to_int(arr[0]);
776 string newuid=arr[1];
777
778 //text wiederherstellen, aber ohne Key und UID
779 if (sizeof(arr) > 2)
780 str = implode(arr[2..]," ");
781 else
782 str = 0;
783
784 switch((int)ERRORD->ReassignIssue(issueid, newuid, str))
785 {
786 case -1:
787 tell_object(PL,
788 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
789 return(1);
790 case -10:
791 tell_object(PL,
792 sprintf("Du hast keine Schreibrechte auf Fehler %d\n",issueid));
793 return 1;
794 case -2:
795 return(0); //offenbar keine neue uid angegeben. (kann nicht)
796 case -3:
797 tell_object(PL,break_string(
798 "Alte == Neue UID ist irgendwie unsinnig...",78));
799 return 1;
800 }
801 // letzten Fehler merken.
802 lfehler = issueid;
803
804 tell_object(PL,break_string(
805 sprintf("Der Fehler der ID %d wurde an die UID %s "
806 "uebertragen.\n", issueid, newuid),78));
807 return 1;
808}
809
810// ************** public 'internal' functions **************
811public string QueryOwner() {return owner;}
812public mixed QueryIssueList() {return issuelist;}
813
814void create() {
815 if (!clonep(ME))
816 return;
817 ::create();
818
819 SetProp(P_SHORT,"Der Fehlerteufel");
820 SetProp(P_LONG,break_string(
821 "Dein Fehlerteufel soll Dir helfen, Informationen "
822 "ueber aufgetretene Fehler zu erhalten. Hierzu fragt er die "
823 "in \"Deinen\" UIDs aufgetretenen Fehler und deren Details vom "
824 "Fehlerspeicher der Mudlib ab. Folgende Kommandos kennt er:",78)
825 +"fehlerabfrage <id> - Fragt Details ueber Fehler mit der ID ab.\n"
826 "fehlerloeschen <id> - Fehler zum Loeschen markieren.\n"
827 "fehlerliste - Fehlerliste der eigenen UIDs anzeigen\n"
828 "fehlerrefresh - Fehlerdaten und UIDs neu einlesen\n"
829 "fehlerfilter - UIDs fuer den Filter angeben (s. manpage!)\n"
830 "fehlermodus - Fehler oder Warnungen ausgeben? (s. manpage)\n"
831 "fehlermonitor - zus. UIDs beobachten (s. manpage)\n"
832 "fnotiz <id> <note> - eine Notiz anhaengen\n"
833 "flock <id> <note> - Fehler vor autom. Loeschen schuetzen\n"
834 "funlock <id> <note> - Fehler zum autom. Loeschen freigeben\n"
835 "ffix <id> <note> - Fehler als gefixt kennzeichnen\n"
836 "funfix <id> <note> - gefixten Fehler als nicht-gefixt markieren\n"
837 "fuebertrage <id> <newuid> <note>\n"
838 " - Fehler an die UID uebertragen\n"
839 );
840 SetProp(P_NAME,"Fehlerteufel");
841 SetProp(P_GENDER,MALE);
842 SetProp(P_WEIGHT,0);
843 SetProp(P_VALUE,0);
844 SetProp(P_SIZE,10);
845 SetProp(P_NODROP,"Den Fehlerteufel behaelst Du lieber bei Dir.\n");
846 SetProp(P_NEVERDROP,1);
847
848 AddId( ({"fehlerteufel","teufel"}) );
849
850 AddCmd(({"fehlerabfrage","fabfrage"}), "CmdFehlerZeigen" );
851 AddCmd(({"fehlerloeschen","floeschen"}), "CmdFehlerLoeschen");
852 AddCmd(({"fehlerliste","fliste", "fehleruebersicht","fuebersicht"}),
853 "CmdFehlerListe");
854 AddCmd(({"fehlerrefresh","frefresh"}),"CmdRefresh");
855 AddCmd(({"fehlerfilter","ffilter"}),"CmdFilter");
856 AddCmd(({"fehlermodus","fmodus"}),"CmdModus");
857 AddCmd(({"fehlermonitor","fmonitor"}),"CmdMonitor");
858 AddCmd(({"fehlernotiz","fnotiz"}),"CmdAddNote");
859 AddCmd(({"fehlerlock","flock","fehlerunlock","funlock"}),
860 "CmdLock");
861 AddCmd(({"fehlerfix","ffix","fehlerunfix","funfix"}),
862 "CmdFix");
863 AddCmd(({"fehleruebertrage","fuebertrage"}),"CmdReassign");
864 AddCmd(({"fehlereingabe", "feingabe"}), "CmdFehlerEingabe");
865}
866
867void init()
868{
869 if (find_call_out("remove") != -1) return;
870
871 // pruefung auf env nicht noetig, move geht nur in ein env und ohne env
872 // auch kein init().
873 if ( !query_once_interactive(environment()) ||
874 !IS_LEARNER(environment())) {
875 // in interactive, aber kein magier -> direkt weg.
876 call_out("remove",0,1);
877 return;
878 }
879 else if (!sizeof(owner))
880 // Env ist Interactiv und Magier (sonst waer man oben rausgeflogen)
881 owner=getuid(environment());
882 else if (owner!=getuid(environment())) {
883 //ok, nicht der Eigentuemer, direkt weg.
884 call_out("remove",0);
885 return;
886 }
887 SetProp(P_EXTRA_LOOK,break_string(
888 "Auf "+environment()->Name(WESSEN)+" Schulter sitzt ein kleiner "
889 "Fehlerteufel, der "
890 +environment()->QueryPronoun(WEM)
891 +" immer wieder etwas ins Ohr fluestert.",78));
892
893 call_out("reset",1);
894
895 ::init();
896}
897
898public mixed Configure(mixed data)
899{
900 if (!data)
901 {
902 return (["filteruids":filteruids,
903 "filterstatus":filterstatus,
904 "modus":modus,
905 "monitoruids":monitoruids,
906 "fehlerzahl": fehlerzahl]);
907 }
908 else if (mappingp(data))
909 {
910 if (member(data,"filteruids") && pointerp(data["filteruids"]))
911 filteruids=data["filteruids"];
912 if (member(data,"filterstatus") && intp(data["filterstatus"]))
913 filterstatus=data["filterstatus"];
914 if (member(data,"modus") && intp(data["modus"]))
915 modus=data["modus"];
916 if (member(data,"monitoruids") && pointerp(data["monitoruids"]))
917 monitoruids=data["monitoruids"];
918 if (member(data,"fehlerzahl") && intp(data["fehlerzahl"]))
919 fehlerzahl=data["fehlerzahl"];
920 return 1;
921 }
922 return 0;
923}
924
925mapping _query_autoloadobj()
926{
927 return Configure(0);
928}
929
930mapping _set_autoloadobj(mixed data)
931{
932 Configure(data);
933 return _query_autoloadobj();
934}
935
936
937void reset()
938{
939 get_uids();
940 int neuefehlerzahl=get_issuelist();
941
942 if (fehlerzahl < neuefehlerzahl)
943 tell_object(environment(ME), break_string(
944 "Deine Fehlerliste ist soeben laenger geworden.",78,
945 "Dein Fehlerteufel teilt Dir mit: "));
946 else if (fehlerzahl > neuefehlerzahl)
947 tell_object(environment(ME), break_string(
948 "Deine Fehlerliste ist soeben kuerzer geworden.",78,
949 "Dein Fehlerteufel teilt Dir mit: "));
950 fehlerzahl = neuefehlerzahl;
951}
952
953// ******** private functions *********************
954private void get_uids()
955{
956 uids=(string *)master()->QueryUIDsForWizard(owner);
957 xmonitoruids=({});
958 if (sizeof(monitoruids))
959 {
960 closure cl=symbol_function("QueryUIDAlias", master());
961 foreach(string uid: monitoruids) {
962 xmonitoruids += (string*)funcall(cl, uid);
963 }
964 }
965}
966
967/* Holt sich aus dem ErrorD die Liste ungeloeschter und ungefixter Fehler fuer
968 * fuer die UIDs des Magier fuer alle Typen
969 */
970private varargs int get_issuelist(int lmodus)
971{
972 int count;
973
974 if (!lmodus)
975 lmodus=modus;
976
977 issuelist=m_allocate(sizeof(ALL_ERR_TYPES),1);
978
979 foreach(int type: ALL_ERR_TYPES)
980 {
981 if (type & lmodus)
982 {
983 //DEBUG(sprintf("Type: %d\n",type));
984 foreach(string uid : uids + xmonitoruids)
985 {
986 //DEBUG(sprintf("Type: %d, UID: %s\n",type,uid));
987 < <int|string>* >* list =
988 (< <int|string>* >*)ERRORD->QueryIssueList(type,uid);
989 count += sizeof(list);
990
991 if (!member(issuelist, type))
992 issuelist += ([ type: ([ uid: list ]) ]);
993 else if (!member(issuelist[type], uid))
994 issuelist[type] += ([uid: list ]);
995 }
996 }
997 }
998 return count;
999}
1000