blob: c892cfb3c4991edefdb46beaea33c9c3662cffdf [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
Bugfixa75344d2017-06-16 14:04:48 +0200302 | T_REPORTED_IDEA | T_REPORTED_TYPO | T_REPORTED_MD |
303 T_REPORTED_SYNTAX;
MG Mud User88f12472016-06-24 23:31:02 +0200304 break;
305 case "fehler":
306 case "error":
307 case "errors":
308 lmodus=T_RTERROR | T_CTERROR | T_REPORTED_ERR;
309 break;
310 case "warnungen":
311 case "warnung":
312 case "warning":
313 case "warnings":
314 lmodus=T_RTWARN | T_CTWARN;
315 break;
316 case "laufzeitfehler":
317 lmodus=T_RTERROR;
318 break;
319 case "ladezeitfehler":
320 lmodus=T_CTERROR;
321 break;
322 case "fehlerhinweis":
323 case "fehlerhinweise":
324 case "hinweise":
325 lmodus=T_REPORTED_ERR;
326 break;
327 case "ideen":
328 case "idee":
329 lmodus=T_REPORTED_IDEA;
330 break;
331 case "md":
332 lmodus=T_REPORTED_MD;
333 break;
334 case "typo":
335 case "typos":
336 lmodus=T_REPORTED_TYPO;
337 break;
Bugfixa75344d2017-06-16 14:04:48 +0200338 case "syntax":
339 case "syntaxhinweis":
340 case "syntaxhinweise":
341 lmodus=T_REPORTED_SYNTAX;
342 break;
MG Mud User88f12472016-06-24 23:31:02 +0200343 case "laufzeitwarnungen":
344 case "runtimewarnings":
345 lmodus=T_RTWARN;
346 break;
347 case "ladezeitwarnungen":
348 case "compiletimewarnings":
349 lmodus=T_CTWARN;
350 break;
351 default:
352 lmodus=modus;
353 }
354 return lmodus;
355}
356
357private string * errorlabel(int t)
358{
359 switch(t) {
360 case T_RTERROR:
361 return ({"Laufzeitfehler","Laufzeitfehler","Dieser Laufzeitfehler"});
362 case T_REPORTED_ERR:
363 return ({"Fehlerhinweis","Fehlerhinweise","Dieser Fehlerhinweis"});
364 case T_REPORTED_IDEA:
365 return ({"Idee","Ideen","Diese Idee"});
366 case T_REPORTED_MD:
367 return ({"fehlende Detail","fehlende Details","Dieses fehlende Detail"});
368 case T_REPORTED_TYPO:
369 return ({"Typo","Typos","Dieser Typo"});
Bugfixa75344d2017-06-16 14:04:48 +0200370 case T_REPORTED_SYNTAX:
371 return ({"Syntaxhinweis","Syntaxhinweise","Dieser Syntaxhinweis"});
MG Mud User88f12472016-06-24 23:31:02 +0200372 case T_RTWARN:
373 return ({"Laufzeitwarnung","Laufzeitwarnungen","Diese Laufzeitwarnung"});
374 case T_CTWARN:
375 return ({"Ladezeitwarnung", "Ladezeitwarnungen","Diese Ladezeitwarnung"});
376 case T_CTERROR:
377 return ({"Ladezeitfehler","Ladezeitfehler","Dieser Ladezeitfehler"});
378 }
379 raise_error("Unkannter Fehlertyp: "+t+"\n");
380 return 0;
381}
382
383public int CmdFehlerListe(string arg) {
384 string txt;
385 //string *luids;
386 int lmodus; // modus fuer diese Liste
387 mapping fehlerbackup;
388
389 if (stringp(arg) && sizeof(arg))
390 {
391 lmodus=select_modus(arg);
392 if (lmodus != modus)
393 {
394 fehlerbackup=issuelist; // Fehlerliste von 'modus' aufheben
395 get_issuelist(lmodus); // neue Fehlerliste holen
396 }
397 }
398 else
399 lmodus=modus;
400/*
401 if (!fehlerzahl)
402 {
403 txt="Fuer Deine UIDs sind keine Fehler/Warnungen bekannt. :-)\n";
404 tell_object(PL,txt);
405 return 1;
406 }
407*/
408 foreach(int typ, mapping typemap : issuelist)
409 {
410 if (!(typ & lmodus))
411 continue; // Type nicht gewaehlt.
412 txt="";
413 if (!sizeof(typemap)) {
414 tell_object(PL,
415 "Es sind keine " + errorlabel(typ)[1] + "Deiner UIDs bekannt. :-)");
416 continue;
417 }
418 foreach(string uid, < <int|string>* >* list : typemap)
419 {
420 if (!sizeof(list)) continue;
421 if (filterstatus && member(filteruids, uid) > -1) continue;
422 //txt+=sprintf("%s:\n", uid);
423 foreach(<int|string>* row : list)
424 {
425 txt+=sprintf("%:6d | %:40-s | %:26-s\n",
426 row[0], row[1], row[2]);
427 }
428 }
429 if (txt && sizeof(txt))
430 {
431 txt = sprintf("\nFuer Deine UIDs sind folgende %s bekannt (Filter: %s):\n"
432 "%:6|s | %:40|s | %s\n",
433 errorlabel(typ)[1], (filterstatus ? "an" : "aus"),
434 "ID", "Loadname", "UID")
435 + txt;
436 tell_object(PL, txt);
437 }
438 else
439 {
440 tell_object(PL, sprintf(
441 "\nFuer Deine UIDs sind keine %s bekannt (Filter: %s):\n",
442 errorlabel(typ)[1], (filterstatus ? "an" : "aus")));
443 }
444 }
445
446 if (mappingp(fehlerbackup) && modus!=lmodus)
447 issuelist=fehlerbackup; // fehlerliste fuer 'modus' restaurieren
448 return 1;
449}
450
451public int CmdFilter(string arg) {
452
453 arg=(string)PL->_unparsed_args(0);
454
455 if (!stringp(arg) || !sizeof(arg)) {
456 tell_object(PL,break_string(
457 "Momentan interessieren Dich folgende UIDs nicht"
458 +(filterstatus ? " (Filter an):\n" : " (Filter aus):\n")
459 +CountUp(filteruids)+"\n", 78,"",BS_LEAVE_MY_LFS));
460 return 1;
461 }
462
463 if (arg=="keine") {
464 filteruids=({});
465 filterstatus=1;
466 tell_object(PL,break_string(
467 "Dein Fehlerteufel wird Dir nun nur noch ausgewaehlte "
468 "Fehler berichten. Momentan hast Du keine UIDs ausgeblendet. "
469 "(Filter an)",78));
470 }
471 else if (arg=="alle") {
472 filterstatus=1;
473 filteruids=uids;
474 tell_object(PL,break_string(
475 "Dein Fehlerteufel wird Dir nun nur noch ausgewaehlte "
476 "Fehler berichten. Du blendest momentan alle UIDs aus. "
477 "(Filter an)",78));
478 }
479 else if (arg=="aus") {
480 filterstatus=0;
481 tell_object(PL,break_string(
482 "Dein Fehlerteufel wird Dir nun wieder alle Fehler berichten. ",
483 78));
484 }
485 else if (arg=="an" || arg=="ein") {
486 filterstatus=1;
487 tell_object(PL,break_string(
488 "Dein Fehlerteufel wird Dir nun nur noch ausgewaehlte "
489 "Fehler berichten.",78));
490 }
491 else {
492 foreach(string uid: explode(arg," ")-({""})) {
493 if (sizeof(uid)>1 && uid[0]=='+') {
494 if (member(filteruids,uid[1..])==-1)
495 filteruids+=({uid[1..]});
496 }
497 else if (sizeof(uid)>1 && uid[0]=='-') {
498 filteruids-=({uid[1..]});
499 }
500 else {
501 if (member(filteruids,uid)==-1)
502 filteruids+=({uid});
503 else
504 filteruids-=({uid});
505 }
506 }
507 }
508
509 tell_object(PL,break_string(
510 "Momentan interessieren Dich folgende UIDs nicht"
511 +(filterstatus ? " (Filter an):\n" : " (Filter aus):\n")
512 +CountUp(filteruids)+"\n", 78,"",BS_LEAVE_MY_LFS));
513
514 return 1;
515}
516
517public int CmdMonitor(string arg) {
518
519 arg=(string)PL->_unparsed_args(0);
520
521 if (!stringp(arg) || !sizeof(arg)) {
522 tell_object(PL,break_string(
523 "Momentan interessieren Dich folgende UIDs zusaetzlich zu Deinen: \n"
524 +(sizeof(monitoruids) ? CountUp(monitoruids) : "")
525 +"\n", 78,"",BS_LEAVE_MY_LFS));
526 return 1;
527 }
528
529 if (arg=="keine") {
530 monitoruids=({});
531 xmonitoruids=({});
532 tell_object(PL,break_string(
533 "Dein Fehlerteufel wird Dir nun nur noch "
534 "Fehler Deiner eigenen UIDs berichten.",78));
535 return 1;
536 }
537 else {
538 foreach(string uid: explode(arg," ")-({""})) {
539 if (sizeof(uid)>1 && uid[0]=='+') {
540 if (member(monitoruids,uid[1..])==-1)
541 monitoruids+=({uid[1..]});
542 }
543 else if (sizeof(uid)>1 && uid[0]=='-') {
544 monitoruids-=({uid[1..]});
545 }
546 else {
547 if (member(monitoruids,uid)==-1)
548 monitoruids+=({uid});
549 else
550 monitoruids-=({uid});
551 }
552 }
553 }
554 get_uids();
555 tell_object(PL,break_string(
556 "Momentan interessieren Dich folgende UIDs zusaetzlich zu Deinen: \n"
557 +(sizeof(monitoruids) ? CountUp(monitoruids) : "")
558 +"\n", 78,"",BS_LEAVE_MY_LFS));
559
560 return 1;
561}
562
563public int CmdModus(string arg) {
564 string txt;
565
566 // Argument verwursten
567 if (stringp(arg) && sizeof(arg)) {
568 modus = select_modus(arg);
569 reset(); // neue Fehlerliste holen
570 }
571 // aktuelle Einstellung ausgeben.
572 string *modstr=({});
573 if (modus & T_RTERROR)
574 modstr+=({"Fehler (Laufzeit)"});
575 if (modus & T_RTWARN)
576 modstr+=({"Warnungen (Laufzeit)"});
577 if (modus & T_CTERROR)
578 modstr+=({"Fehler (Ladezeit)"});
579 if (modus & T_CTWARN)
580 modstr+=({"Warnungen (Ladezeit)"});
581 if (modus & T_REPORTED_ERR)
582 modstr+=({"Fehlerhinweise"});
583 if (modus & T_REPORTED_IDEA)
584 modstr+=({"Idee"});
585 if (modus & T_REPORTED_MD)
586 modstr+=({"fehlende Details"});
587 if (modus & T_REPORTED_TYPO)
588 modstr+=({"Typo"});
Bugfixa75344d2017-06-16 14:04:48 +0200589 if(modus&T_REPORTED_SYNTAX)
590 modstr+=({"Syntaxhinweise"});
MG Mud User88f12472016-06-24 23:31:02 +0200591
592 tell_object(PL, break_string(
593 "Dein Fehlerteufel wird Dir nun ueber aufgetretene "
594 +CountUp(modstr)+" Bericht erstatten.",78));
595 return(1);
596}
597
598int CmdAddNote(string str) {
599 string *arr;
600
601 notify_fail("Bitte eine ID und einen Text angeben!\n");
602 if(!objectp(TI))
603 return 0;
604
605 str=(string)PL->_unparsed_args(0);
606 if (!stringp(str) || !sizeof(str))
607 return 0;
608
609 arr=explode(str," ")-({""});
610 if (sizeof(arr)<2)
611 return 0;
612 int issueid = to_int(arr[0]);
613
614 str=implode(arr[1..]," "); //text wiederherstellen, aber ohne ID
615
616 switch((int)ERRORD->AddNote(issueid,str))
617 {
618 case -1:
619 tell_object(PL,
620 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
621 return 1;
622 case -3:
623 return 0; //offenbar keine Notiz angegeben.
624 }
625 // letzten Fehler merken.
626 lfehler = issueid;
627
628 tell_object(PL,
629 sprintf("Deine Notiz wurde zu %d hinzugefuegt.\n",
630 issueid));
631 return 1;
632}
633
634int CmdFix(string str)
635{
636 string *arr;
637 int fixing, res;
638
639 notify_fail("Bitte eine ID und optional eine Notiz angeben!\n");
640 if(!objectp(TI))
641 return 0;
642
643 str=(string)PL->_unparsed_args(0);
644 if (!stringp(str) || !sizeof(str))
645 return 0;
646
647 arr=explode(str," ")-({""});
648 if (!sizeof(arr))
649 return 0;
650
651 int issueid=to_int(arr[0]);
652 if (sizeof(arr)>1)
653 str=implode(arr[1..]," "); //text wiederherstellen, aber ohne Key
654 else str=0;
655
656 if (query_verb()=="ffix" || query_verb()=="fehlerfix")
657 {
658 fixing=1;
659 res = (int)ERRORD->ResolveIssue(issueid, str);
660 }
661 else
662 {
663 res = (int)ERRORD->ReOpenIssue(issueid, str);
664 }
665
666 if (res==-1)
667 {
668 tell_object(PL,
669 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
670 }
671 else if (res==-10)
672 {
673 tell_object(PL,
674 "Du hast leider keinen Schreibzugriff diesen Fehler.\n"
675 "Aber vielleicht moechtest Du mit fnotiz eine Notiz anhaengen?\n");
676 }
677 else if (res==-3)
678 {
679 if (fixing)
680 tell_object(PL,"Dieser Fehler ist bereits gefixt.\n");
681 else
682 tell_object(PL,"Dieser Fehler ist noch nicht gefixt.\n");
683 }
684 else if (res==1)
685 {
686 tell_object(PL,
687 sprintf("Fehler %d als gefixt markiert.\n",issueid));
688 }
689 else if (res==0)
690 {
691 tell_object(PL,
692 sprintf("Fehler %d als nicht gefixt markiert.\n",issueid));
693 }
694 // letzten Fehler merken.
695 lfehler = issueid;
696
697 return 1;
698}
699
700int CmdLock(string str) {
701 string *arr;
702 int locking;
703 int res;
704
705 notify_fail("Bitte eine ID und optional eine Notiz angeben!\n");
706 if(!objectp(TI))
707 return 0;
708
709 str=(string)PL->_unparsed_args(0);
710 if (!stringp(str) || !sizeof(str))
711 return 0;
712
713 arr=explode(str," ")-({""});
714 if (!sizeof(arr))
715 return 0;
716
717 int issueid=to_int(arr[0]);
718 if (sizeof(arr)>1)
719 str=implode(arr[1..]," "); //text wiederherstellen, aber ohne Key
720 else str=0;
721
722 if (query_verb()=="flock" || query_verb()=="fehlerlock")
723 {
724 locking=1;
725 res=(int)ERRORD->LockIssue(issueid,str);
726 }
727 else
728 {
729 res=(int)ERRORD->UnlockIssue(issueid,str);
730 }
731
732 if (res==-1)
733 {
734 tell_object(PL,
735 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
736 }
737 else if (res==-10)
738 {
739 tell_object(PL,
740 "Du hast leider keinen Schreibzugriff diesen Fehler.\n");
741 }
742 else if (res==-3)
743 {
744 if (locking)
745 tell_object(PL,
746 "Dieser Fehler ist bereits vor autom. Loeschen geschuetzt.\n");
747 else
748 tell_object(PL,
749 "Dieser Fehler ist bereits zum autom. Loeschen freigegeben.\n");
750 }
751 else if (res==-2)
752 {
753 tell_object(PL,
754 "Dieser Fehler ist bereits gefixt und wird bald geloescht.\n");
755 }
756 else if (res==1)
757 {
758 tell_object(PL,
759 sprintf("Fehler %d vor autom. Loeschen geschuetzt.\n",issueid));
760 }
761 else if (res==0)
762 {
763 tell_object(PL,
764 sprintf("Fehler %d zum autom. Loeschen freigegeben.\n",issueid));
765 }
766 // letzten Fehler merken.
767 lfehler = issueid;
768
769 return 1;
770}
771
772int CmdReassign(string str) {
773
774 notify_fail("Bitte eine ID, die neue UID und ggf. eine Notiz angeben!\n");
775 if(!objectp(TI))
776 return 0;
777
778 str=(string)PL->_unparsed_args(0);
779 if (!stringp(str) || !sizeof(str))
780 return 0;
781
782 string *arr=explode(str," ")-({""});
783 if (sizeof(arr)<2)
784 return 0;
785 int issueid=to_int(arr[0]);
786 string newuid=arr[1];
787
788 //text wiederherstellen, aber ohne Key und UID
789 if (sizeof(arr) > 2)
790 str = implode(arr[2..]," ");
791 else
792 str = 0;
793
794 switch((int)ERRORD->ReassignIssue(issueid, newuid, str))
795 {
796 case -1:
797 tell_object(PL,
798 sprintf("Es gibt keinen Fehler mit der ID: %d\n",issueid));
799 return(1);
800 case -10:
801 tell_object(PL,
802 sprintf("Du hast keine Schreibrechte auf Fehler %d\n",issueid));
803 return 1;
804 case -2:
805 return(0); //offenbar keine neue uid angegeben. (kann nicht)
806 case -3:
807 tell_object(PL,break_string(
808 "Alte == Neue UID ist irgendwie unsinnig...",78));
809 return 1;
810 }
811 // letzten Fehler merken.
812 lfehler = issueid;
813
814 tell_object(PL,break_string(
815 sprintf("Der Fehler der ID %d wurde an die UID %s "
816 "uebertragen.\n", issueid, newuid),78));
817 return 1;
818}
819
820// ************** public 'internal' functions **************
821public string QueryOwner() {return owner;}
822public mixed QueryIssueList() {return issuelist;}
823
824void create() {
825 if (!clonep(ME))
826 return;
827 ::create();
828
829 SetProp(P_SHORT,"Der Fehlerteufel");
830 SetProp(P_LONG,break_string(
831 "Dein Fehlerteufel soll Dir helfen, Informationen "
832 "ueber aufgetretene Fehler zu erhalten. Hierzu fragt er die "
833 "in \"Deinen\" UIDs aufgetretenen Fehler und deren Details vom "
834 "Fehlerspeicher der Mudlib ab. Folgende Kommandos kennt er:",78)
835 +"fehlerabfrage <id> - Fragt Details ueber Fehler mit der ID ab.\n"
836 "fehlerloeschen <id> - Fehler zum Loeschen markieren.\n"
837 "fehlerliste - Fehlerliste der eigenen UIDs anzeigen\n"
838 "fehlerrefresh - Fehlerdaten und UIDs neu einlesen\n"
839 "fehlerfilter - UIDs fuer den Filter angeben (s. manpage!)\n"
840 "fehlermodus - Fehler oder Warnungen ausgeben? (s. manpage)\n"
841 "fehlermonitor - zus. UIDs beobachten (s. manpage)\n"
842 "fnotiz <id> <note> - eine Notiz anhaengen\n"
843 "flock <id> <note> - Fehler vor autom. Loeschen schuetzen\n"
844 "funlock <id> <note> - Fehler zum autom. Loeschen freigeben\n"
845 "ffix <id> <note> - Fehler als gefixt kennzeichnen\n"
846 "funfix <id> <note> - gefixten Fehler als nicht-gefixt markieren\n"
847 "fuebertrage <id> <newuid> <note>\n"
848 " - Fehler an die UID uebertragen\n"
849 );
850 SetProp(P_NAME,"Fehlerteufel");
851 SetProp(P_GENDER,MALE);
852 SetProp(P_WEIGHT,0);
853 SetProp(P_VALUE,0);
854 SetProp(P_SIZE,10);
855 SetProp(P_NODROP,"Den Fehlerteufel behaelst Du lieber bei Dir.\n");
856 SetProp(P_NEVERDROP,1);
857
858 AddId( ({"fehlerteufel","teufel"}) );
859
860 AddCmd(({"fehlerabfrage","fabfrage"}), "CmdFehlerZeigen" );
861 AddCmd(({"fehlerloeschen","floeschen"}), "CmdFehlerLoeschen");
862 AddCmd(({"fehlerliste","fliste", "fehleruebersicht","fuebersicht"}),
863 "CmdFehlerListe");
864 AddCmd(({"fehlerrefresh","frefresh"}),"CmdRefresh");
865 AddCmd(({"fehlerfilter","ffilter"}),"CmdFilter");
866 AddCmd(({"fehlermodus","fmodus"}),"CmdModus");
867 AddCmd(({"fehlermonitor","fmonitor"}),"CmdMonitor");
868 AddCmd(({"fehlernotiz","fnotiz"}),"CmdAddNote");
869 AddCmd(({"fehlerlock","flock","fehlerunlock","funlock"}),
870 "CmdLock");
871 AddCmd(({"fehlerfix","ffix","fehlerunfix","funfix"}),
872 "CmdFix");
873 AddCmd(({"fehleruebertrage","fuebertrage"}),"CmdReassign");
874 AddCmd(({"fehlereingabe", "feingabe"}), "CmdFehlerEingabe");
875}
876
877void init()
878{
879 if (find_call_out("remove") != -1) return;
880
881 // pruefung auf env nicht noetig, move geht nur in ein env und ohne env
882 // auch kein init().
883 if ( !query_once_interactive(environment()) ||
884 !IS_LEARNER(environment())) {
885 // in interactive, aber kein magier -> direkt weg.
886 call_out("remove",0,1);
887 return;
888 }
889 else if (!sizeof(owner))
890 // Env ist Interactiv und Magier (sonst waer man oben rausgeflogen)
891 owner=getuid(environment());
892 else if (owner!=getuid(environment())) {
893 //ok, nicht der Eigentuemer, direkt weg.
894 call_out("remove",0);
895 return;
896 }
897 SetProp(P_EXTRA_LOOK,break_string(
898 "Auf "+environment()->Name(WESSEN)+" Schulter sitzt ein kleiner "
899 "Fehlerteufel, der "
900 +environment()->QueryPronoun(WEM)
901 +" immer wieder etwas ins Ohr fluestert.",78));
902
903 call_out("reset",1);
904
905 ::init();
906}
907
908public mixed Configure(mixed data)
909{
910 if (!data)
911 {
912 return (["filteruids":filteruids,
913 "filterstatus":filterstatus,
914 "modus":modus,
915 "monitoruids":monitoruids,
916 "fehlerzahl": fehlerzahl]);
917 }
918 else if (mappingp(data))
919 {
920 if (member(data,"filteruids") && pointerp(data["filteruids"]))
921 filteruids=data["filteruids"];
922 if (member(data,"filterstatus") && intp(data["filterstatus"]))
923 filterstatus=data["filterstatus"];
924 if (member(data,"modus") && intp(data["modus"]))
925 modus=data["modus"];
926 if (member(data,"monitoruids") && pointerp(data["monitoruids"]))
927 monitoruids=data["monitoruids"];
928 if (member(data,"fehlerzahl") && intp(data["fehlerzahl"]))
929 fehlerzahl=data["fehlerzahl"];
930 return 1;
931 }
932 return 0;
933}
934
935mapping _query_autoloadobj()
936{
937 return Configure(0);
938}
939
940mapping _set_autoloadobj(mixed data)
941{
942 Configure(data);
943 return _query_autoloadobj();
944}
945
946
947void reset()
948{
949 get_uids();
950 int neuefehlerzahl=get_issuelist();
951
952 if (fehlerzahl < neuefehlerzahl)
953 tell_object(environment(ME), break_string(
954 "Deine Fehlerliste ist soeben laenger geworden.",78,
955 "Dein Fehlerteufel teilt Dir mit: "));
956 else if (fehlerzahl > neuefehlerzahl)
957 tell_object(environment(ME), break_string(
958 "Deine Fehlerliste ist soeben kuerzer geworden.",78,
959 "Dein Fehlerteufel teilt Dir mit: "));
960 fehlerzahl = neuefehlerzahl;
961}
962
963// ******** private functions *********************
964private void get_uids()
965{
966 uids=(string *)master()->QueryUIDsForWizard(owner);
967 xmonitoruids=({});
968 if (sizeof(monitoruids))
969 {
970 closure cl=symbol_function("QueryUIDAlias", master());
971 foreach(string uid: monitoruids) {
972 xmonitoruids += (string*)funcall(cl, uid);
973 }
974 }
975}
976
977/* Holt sich aus dem ErrorD die Liste ungeloeschter und ungefixter Fehler fuer
978 * fuer die UIDs des Magier fuer alle Typen
979 */
980private varargs int get_issuelist(int lmodus)
981{
982 int count;
983
984 if (!lmodus)
985 lmodus=modus;
986
987 issuelist=m_allocate(sizeof(ALL_ERR_TYPES),1);
988
989 foreach(int type: ALL_ERR_TYPES)
990 {
991 if (type & lmodus)
992 {
993 //DEBUG(sprintf("Type: %d\n",type));
994 foreach(string uid : uids + xmonitoruids)
995 {
996 //DEBUG(sprintf("Type: %d, UID: %s\n",type,uid));
997 < <int|string>* >* list =
998 (< <int|string>* >*)ERRORD->QueryIssueList(type,uid);
999 count += sizeof(list);
1000
1001 if (!member(issuelist, type))
1002 issuelist += ([ type: ([ uid: list ]) ]);
1003 else if (!member(issuelist[type], uid))
1004 issuelist[type] += ([uid: list ]);
1005 }
1006 }
1007 }
1008 return count;
1009}
1010