diff --git a/buildapp.xml b/buildapp.xml index 3e623a92..22a941ca 100644 --- a/buildapp.xml +++ b/buildapp.xml @@ -15,8 +15,8 @@ name="Structorizer" displayname="Structorizer" identifier="lu.fisch.Structorizer" - shortversion="3.30-02" - version="3.30-02" + shortversion="3.30-03" + version="3.30-03" icon="icons/Structorizer.icns" mainclassname="Structorizer" copyright="Bob Fisch" diff --git a/samples/arrz/ELIZA_2.3.arrz b/samples/arrz/ELIZA_2.3.arrz new file mode 100644 index 00000000..e7af4068 Binary files /dev/null and b/samples/arrz/ELIZA_2.3.arrz differ diff --git a/samples/export/BASIC0/ELIZA_2.3.bas b/samples/export/BASIC0/ELIZA_2.3.bas new file mode 100644 index 00000000..16899e1f --- /dev/null +++ b/samples/export/BASIC0/ELIZA_2.3.bas @@ -0,0 +1,564 @@ +10 REM Concept and lisp implementation published by Joseph Weizenbaum (MIT): +20 REM "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +30 REM Computational Linguistis 1(1966)9, pp. 36-45 +40 REM Revision history: +50 REM 2016-10-06 Initial version +60 REM 2017-03-29 Two diagrams updated (comments translated to English) +70 REM 2017-03-29 More keywords and replies added +80 REM 2019-03-14 Replies and mapping reorganised for easier maintenance +90 REM 2019-03-15 key map joined from keyword array and index map +100 REM 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +110 REM 2019-11-28 New global type "History" (to ensure a homogenous array) +120 REM Generated by Structorizer 3.30-03 +130 REM +140 REM Copyright (C) 2018-05-14 Kay Gürtzig +150 REM License: GPLv3-link +160 REM GNU General Public License (V 3) +170 REM https://www.gnu.org/licenses/gpl.html +180 REM http://www.gnu.de/documents/gpl.de.html +190 REM +200 REM +210 REM program ELIZA +220 REM TODO: add the respective type suffixes to your variable names if required +230 REM Title information +240 PRINT "************* ELIZA **************" +250 PRINT "* Original design by J. Weizenbaum" +260 PRINT "**********************************" +270 PRINT "* Adapted for Basic on IBM PC by" +280 PRINT "* - Patricia Danielson" +290 PRINT "* - Paul Hashfield" +300 PRINT "**********************************" +310 PRINT "* Adapted for Structorizer by" +320 PRINT "* - Kay Gürtzig / FH Erfurt 2016" +330 PRINT "* Version: 2.3 (2019-11-28)" +340 PRINT "* (Requires at least Structorizer 3.30-03 to run)" +350 PRINT "**********************************" +360 REM Stores the last five inputs of the user in a ring buffer, +370 REM the second component is the rolling (over-)write index. +380 DIM history AS History +390 LET history.histArray = {"", "", "", "", ""} +400 LET history.histIndex = 0 +410 LET replies = setupReplies() +420 LET reflexions = setupReflexions() +430 LET byePhrases = setupGoodByePhrases() +440 LET keyMap = setupKeywords() +450 LET offsets(length(keyMap)-1) = 0 +460 LET isGone = false +470 REM Starter +480 PRINT "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?" +490 DO +500 INPUT userInput +510 REM Converts the input to lowercase, cuts out interpunctation +520 REM and pads the string +530 LET userInput = normalizeInput(userInput) +540 LET isGone = checkGoodBye(userInput, byePhrases) +550 IF NOT isGone THEN +560 LET reply = "Please don\'t repeat yourself!" +570 LET isRepeated = checkRepetition(history, userInput) +580 IF NOT isRepeated THEN +590 LET findInfo = findKeyword(keyMap, userInput) +600 LET keyIndex = findInfo(0) +610 IF keyIndex < 0 THEN +620 REM Should never happen... +630 LET keyIndex = length(keyMap)-1 +640 END IF +650 LET var entry: KeyMapEntry = keyMap(keyIndex) +660 REM Variable part of the reply +670 LET varPart = "" +680 IF length(entry.keyword) > 0 THEN +690 LET varPart = conjugateStrings(userInput, entry.keyword, findInfo(1), reflexions) +700 END IF +710 LET replyRing = replies(entry.index) +720 LET reply = replyRing(offsets(keyIndex)) +730 LET offsets(keyIndex) = (offsets(keyIndex) + 1) % length(replyRing) +740 LET posAster = pos("*", reply) +750 IF posAster > 0 THEN +760 IF varPart = " " THEN +770 LET reply = "You will have to elaborate more for me to help you." +780 ELSE +790 delete(reply, posAster, 1) +800 insert(varPart, reply, posAster) +810 END IF +820 END IF +830 LET reply = adjustSpelling(reply) +840 END IF +850 PRINT reply +860 END IF +870 LOOP UNTIL isGone +880 END +890 REM +900 REM Cares for correct letter case among others +910 REM TODO: Add type-specific suffixes where necessary! +920 FUNCTION adjustSpelling(sentence AS String) AS String +930 REM TODO: add the respective type suffixes to your variable names if required +940 LET result = sentence +950 LET position = 1 +960 DO WHILE (position <= length(sentence)) AND (copy(sentence, position, 1) = " ") +970 LET position = position + 1 +980 LOOP +990 IF position <= length(sentence) THEN +1000 LET start = copy(sentence, 1, position) +1010 delete(result, 1, position) +1020 insert(uppercase(start), result, 1) +1030 END IF +1040 DIM array3ac43688() AS String = {" i ", " i\'"} +1050 FOR EACH word IN array3ac43688 +1060 LET position = pos(word, result) +1070 DO WHILE position > 0 +1080 delete(result, position+1, 1) +1090 insert("I", result, position+1) +1100 LET position = pos(word, result) +1110 LOOP +1120 NEXT word +1130 RETURN result +1140 END FUNCTION +1150 REM +1160 REM Checks whether the given text contains some kind of +1170 REM good-bye phrase inducing the end of the conversation +1180 REM and if so writes a correspding good-bye message and +1190 REM returns true, otherwise false +1200 REM TODO: Add type-specific suffixes where necessary! +1210 FUNCTION checkGoodBye(text AS String, phrases AS array of array[0..1] of string) AS boolean +1220 REM TODO: add the respective type suffixes to your variable names if required +1230 FOR EACH pair IN phrases +1240 IF pos(pair(0), text) > 0 THEN +1250 LET saidBye = true +1260 PRINT pair(1) +1270 RETURN true +1280 END IF +1290 NEXT pair +1300 return false +1310 END FUNCTION +1320 REM +1330 REM Checks whether newInput has occurred among the recently cached +1340 REM input strings in the histArray component of history and updates the history. +1350 REM TODO: Add type-specific suffixes where necessary! +1360 FUNCTION checkRepetition(history AS History, newInput AS String) AS boolean +1370 REM TODO: add the respective type suffixes to your variable names if required +1380 LET hasOccurred = false +1390 IF length(newInput) > 4 THEN +1400 LET histDepth = length(history.histArray) +1410 FOR i = 0 TO histDepth-1 +1420 IF newInput = history.histArray(i) THEN +1430 LET hasOccurred = true +1440 END IF +1450 NEXT i +1460 LET history.histArray(history.histIndex) = newInput +1470 LET history.histIndex = (history.histIndex + 1) % (histDepth) +1480 END IF +1490 return hasOccurred +1500 END FUNCTION +1510 REM +1520 REM TODO: Add type-specific suffixes where necessary! +1530 FUNCTION conjugateStrings(sentence AS String, key AS String, keyPos AS integer, flexions AS array of array[0..1] of string) AS String +1540 REM TODO: add the respective type suffixes to your variable names if required +1550 LET result = " " + copy(sentence, keyPos + length(key), length(sentence)) + " " +1560 FOR EACH pair IN flexions +1570 LET left = "" +1580 LET right = result +1590 LET position = pos(pair(0), right) +1600 DO WHILE position > 0 +1610 LET left = left + copy(right, 1, position-1) + pair(1) +1620 LET right = copy(right, position + length(pair(0)), length(right)) +1630 LET position = pos(pair(0), right) +1640 LOOP +1650 LET result = left + right +1660 NEXT pair +1670 REM Eliminate multiple spaces +1680 LET position = pos(" ", result) +1690 DO WHILE position > 0 +1700 LET result = copy(result, 1, position-1) + copy(result, position+1, length(result)) +1710 LET position = pos(" ", result) +1720 LOOP +1730 RETURN result +1740 END FUNCTION +1750 REM +1760 REM Looks for the occurrence of the first of the strings +1770 REM contained in keywords within the given sentence (in +1780 REM array order). +1790 REM Returns an array of +1800 REM 0: the index of the first identified keyword (if any, otherwise -1), +1810 REM 1: the position inside sentence (0 if not found) +1820 REM TODO: Add type-specific suffixes where necessary! +1830 FUNCTION findKeyword(keyMap AS const array of KeyMapEntry, sentence AS String) AS array[0..1] of integer +1840 REM TODO: add the respective type suffixes to your variable names if required +1850 REM Contains the index of the keyword and its position in sentence +1860 REM TODO: Check indexBase value (automatically generated) +1870 LET indexBase = 0 +1880 LET result(indexBase + 0) = -1 +1890 LET result(indexBase + 1) = 0 +1900 LET i = 0 +1910 DO WHILE (result(0) < 0) AND (i < length(keyMap)) +1920 LET var entry: KeyMapEntry = keyMap(i) +1930 LET position = pos(entry.keyword, sentence) +1940 IF position > 0 THEN +1950 LET result(0) = i +1960 LET result(1) = position +1970 END IF +1980 LET i = i+1 +1990 LOOP +2000 RETURN result +2010 END FUNCTION +2020 REM +2030 REM Converts the sentence to lowercase, eliminates all +2040 REM interpunction (i.e. ',', '.', ';'), and pads the +2050 REM sentence among blanks +2060 REM TODO: Add type-specific suffixes where necessary! +2070 FUNCTION normalizeInput(sentence AS String) AS String +2080 REM TODO: add the respective type suffixes to your variable names if required +2090 LET sentence = lowercase(sentence) +2100 REM TODO: Specify an appropriate element type for the array! +2110 DIM arrayd492107() AS FIXME_d492107 = {'.', ',', ';', '!', '?'} +2120 FOR EACH symbol IN arrayd492107 +2130 LET position = pos(symbol, sentence) +2140 DO WHILE position > 0 +2150 LET sentence = copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)) +2160 LET position = pos(symbol, sentence) +2170 LOOP +2180 NEXT symbol +2190 LET result = " " + sentence + " " +2200 RETURN result +2210 END FUNCTION +2220 REM +2230 REM TODO: Add type-specific suffixes where necessary! +2240 FUNCTION setupGoodByePhrases() AS array of array[0..1] of string +2250 REM TODO: add the respective type suffixes to your variable names if required +2260 REM TODO: Check indexBase value (automatically generated) +2270 LET indexBase = 0 +2280 LET phrases(0)(indexBase + 0) = " shut" +2290 LET phrases(0)(indexBase + 1) = "Okay. If you feel that way I\'ll shut up. ... Your choice." +2300 REM TODO: Check indexBase value (automatically generated) +2310 LET indexBase = 0 +2320 LET phrases(1)(indexBase + 0) = "bye" +2330 LET phrases(1)(indexBase + 1) = "Well, let\'s end our talk for now. See you later. Bye." +2340 return phrases +2350 END FUNCTION +2360 REM +2370 REM The lower the index the higher the rank of the keyword (search is sequential). +2380 REM The index of the first keyword found in a user sentence maps to a respective +2390 REM reply ring as defined in `setupReplies()´. +2400 REM TODO: Add type-specific suffixes where necessary! +2410 FUNCTION setupKeywords() AS array of KeyMapEntry +2420 REM TODO: add the respective type suffixes to your variable names if required +2430 REM The empty key string (last entry) is the default clause - will always be found +2440 LET keywords(39).keyword = "" +2450 LET keywords(39).index = 29 +2460 LET keywords(0).keyword = "can you " +2470 LET keywords(0).index = 0 +2480 LET keywords(1).keyword = "can i " +2490 LET keywords(1).index = 1 +2500 LET keywords(2).keyword = "you are " +2510 LET keywords(2).index = 2 +2520 LET keywords(3).keyword = "you\'re " +2530 LET keywords(3).index = 2 +2540 LET keywords(4).keyword = "i don't " +2550 LET keywords(4).index = 3 +2560 LET keywords(5).keyword = "i feel " +2570 LET keywords(5).index = 4 +2580 LET keywords(6).keyword = "why don\'t you " +2590 LET keywords(6).index = 5 +2600 LET keywords(7).keyword = "why can\'t i " +2610 LET keywords(7).index = 6 +2620 LET keywords(8).keyword = "are you " +2630 LET keywords(8).index = 7 +2640 LET keywords(9).keyword = "i can\'t " +2650 LET keywords(9).index = 8 +2660 LET keywords(10).keyword = "i am " +2670 LET keywords(10).index = 9 +2680 LET keywords(11).keyword = "i\'m " +2690 LET keywords(11).index = 9 +2700 LET keywords(12).keyword = "you " +2710 LET keywords(12).index = 10 +2720 LET keywords(13).keyword = "i want " +2730 LET keywords(13).index = 11 +2740 LET keywords(14).keyword = "what " +2750 LET keywords(14).index = 12 +2760 LET keywords(15).keyword = "how " +2770 LET keywords(15).index = 12 +2780 LET keywords(16).keyword = "who " +2790 LET keywords(16).index = 12 +2800 LET keywords(17).keyword = "where " +2810 LET keywords(17).index = 12 +2820 LET keywords(18).keyword = "when " +2830 LET keywords(18).index = 12 +2840 LET keywords(19).keyword = "why " +2850 LET keywords(19).index = 12 +2860 LET keywords(20).keyword = "name " +2870 LET keywords(20).index = 13 +2880 LET keywords(21).keyword = "cause " +2890 LET keywords(21).index = 14 +2900 LET keywords(22).keyword = "sorry " +2910 LET keywords(22).index = 15 +2920 LET keywords(23).keyword = "dream " +2930 LET keywords(23).index = 16 +2940 LET keywords(24).keyword = "hello " +2950 LET keywords(24).index = 17 +2960 LET keywords(25).keyword = "hi " +2970 LET keywords(25).index = 17 +2980 LET keywords(26).keyword = "maybe " +2990 LET keywords(26).index = 18 +3000 LET keywords(27).keyword = " no" +3010 LET keywords(27).index = 19 +3020 LET keywords(28).keyword = "your " +3030 LET keywords(28).index = 20 +3040 LET keywords(29).keyword = "always " +3050 LET keywords(29).index = 21 +3060 LET keywords(30).keyword = "think " +3070 LET keywords(30).index = 22 +3080 LET keywords(31).keyword = "alike " +3090 LET keywords(31).index = 23 +3100 LET keywords(32).keyword = "yes " +3110 LET keywords(32).index = 24 +3120 LET keywords(33).keyword = "friend " +3130 LET keywords(33).index = 25 +3140 LET keywords(34).keyword = "computer" +3150 LET keywords(34).index = 26 +3160 LET keywords(35).keyword = "bot " +3170 LET keywords(35).index = 26 +3180 LET keywords(36).keyword = "smartphone" +3190 LET keywords(36).index = 27 +3200 LET keywords(37).keyword = "father " +3210 LET keywords(37).index = 28 +3220 LET keywords(38).keyword = "mother " +3230 LET keywords(38).index = 28 +3240 return keywords +3250 END FUNCTION +3260 REM +3270 REM Returns an array of pairs of mutualy substitutable +3280 REM TODO: Add type-specific suffixes where necessary! +3290 FUNCTION setupReflexions() AS array of array[0..1] of string +3300 REM TODO: add the respective type suffixes to your variable names if required +3310 REM TODO: Check indexBase value (automatically generated) +3320 LET indexBase = 0 +3330 LET reflexions(0)(indexBase + 0) = " are " +3340 LET reflexions(0)(indexBase + 1) = " am " +3350 REM TODO: Check indexBase value (automatically generated) +3360 LET indexBase = 0 +3370 LET reflexions(1)(indexBase + 0) = " were " +3380 LET reflexions(1)(indexBase + 1) = " was " +3390 REM TODO: Check indexBase value (automatically generated) +3400 LET indexBase = 0 +3410 LET reflexions(2)(indexBase + 0) = " you " +3420 LET reflexions(2)(indexBase + 1) = " I " +3430 REM TODO: Check indexBase value (automatically generated) +3440 LET indexBase = 0 +3450 LET reflexions(3)(indexBase + 0) = " your" +3460 LET reflexions(3)(indexBase + 1) = " my" +3470 REM TODO: Check indexBase value (automatically generated) +3480 LET indexBase = 0 +3490 LET reflexions(4)(indexBase + 0) = " i\'ve " +3500 LET reflexions(4)(indexBase + 1) = " you\'ve " +3510 REM TODO: Check indexBase value (automatically generated) +3520 LET indexBase = 0 +3530 LET reflexions(5)(indexBase + 0) = " i\'m " +3540 LET reflexions(5)(indexBase + 1) = " you\'re " +3550 REM TODO: Check indexBase value (automatically generated) +3560 LET indexBase = 0 +3570 LET reflexions(6)(indexBase + 0) = " me " +3580 LET reflexions(6)(indexBase + 1) = " you " +3590 REM TODO: Check indexBase value (automatically generated) +3600 LET indexBase = 0 +3610 LET reflexions(7)(indexBase + 0) = " my " +3620 LET reflexions(7)(indexBase + 1) = " your " +3630 REM TODO: Check indexBase value (automatically generated) +3640 LET indexBase = 0 +3650 LET reflexions(8)(indexBase + 0) = " i " +3660 LET reflexions(8)(indexBase + 1) = " you " +3670 REM TODO: Check indexBase value (automatically generated) +3680 LET indexBase = 0 +3690 LET reflexions(9)(indexBase + 0) = " am " +3700 LET reflexions(9)(indexBase + 1) = " are " +3710 return reflexions +3720 END FUNCTION +3730 REM +3740 REM This routine sets up the reply rings addressed by the key words defined in +3750 REM routine `setupKeywords()´ and mapped hitherto by the cross table defined +3760 REM in `setupMapping()´ +3770 REM TODO: Add type-specific suffixes where necessary! +3780 FUNCTION setupReplies() AS array of array of string +3790 REM TODO: add the respective type suffixes to your variable names if required +3800 var replies: array of array of String +3810 REM We start with the highest index for performance reasons +3820 REM (is to avoid frequent array resizing) +3830 REM TODO: Check indexBase value (automatically generated) +3840 LET indexBase = 0 +3850 LET replies(29)(indexBase + 0) = "Say, do you have any psychological problems?" +3860 LET replies(29)(indexBase + 1) = "What does that suggest to you?" +3870 LET replies(29)(indexBase + 2) = "I see." +3880 LET replies(29)(indexBase + 3) = "I'm not sure I understand you fully." +3890 LET replies(29)(indexBase + 4) = "Come come elucidate your thoughts." +3900 LET replies(29)(indexBase + 5) = "Can you elaborate on that?" +3910 LET replies(29)(indexBase + 6) = "That is quite interesting." +3920 REM TODO: Check indexBase value (automatically generated) +3930 LET indexBase = 0 +3940 LET replies(0)(indexBase + 0) = "Don't you believe that I can*?" +3950 LET replies(0)(indexBase + 1) = "Perhaps you would like to be like me?" +3960 LET replies(0)(indexBase + 2) = "You want me to be able to*?" +3970 REM TODO: Check indexBase value (automatically generated) +3980 LET indexBase = 0 +3990 LET replies(1)(indexBase + 0) = "Perhaps you don't want to*?" +4000 LET replies(1)(indexBase + 1) = "Do you want to be able to*?" +4010 REM TODO: Check indexBase value (automatically generated) +4020 LET indexBase = 0 +4030 LET replies(2)(indexBase + 0) = "What makes you think I am*?" +4040 LET replies(2)(indexBase + 1) = "Does it please you to believe I am*?" +4050 LET replies(2)(indexBase + 2) = "Perhaps you would like to be*?" +4060 LET replies(2)(indexBase + 3) = "Do you sometimes wish you were*?" +4070 REM TODO: Check indexBase value (automatically generated) +4080 LET indexBase = 0 +4090 LET replies(3)(indexBase + 0) = "Don't you really*?" +4100 LET replies(3)(indexBase + 1) = "Why don't you*?" +4110 LET replies(3)(indexBase + 2) = "Do you wish to be able to*?" +4120 LET replies(3)(indexBase + 3) = "Does that trouble you*?" +4130 REM TODO: Check indexBase value (automatically generated) +4140 LET indexBase = 0 +4150 LET replies(4)(indexBase + 0) = "Do you often feel*?" +4160 LET replies(4)(indexBase + 1) = "Are you afraid of feeling*?" +4170 LET replies(4)(indexBase + 2) = "Do you enjoy feeling*?" +4180 REM TODO: Check indexBase value (automatically generated) +4190 LET indexBase = 0 +4200 LET replies(5)(indexBase + 0) = "Do you really believe I don't*?" +4210 LET replies(5)(indexBase + 1) = "Perhaps in good time I will*." +4220 LET replies(5)(indexBase + 2) = "Do you want me to*?" +4230 REM TODO: Check indexBase value (automatically generated) +4240 LET indexBase = 0 +4250 LET replies(6)(indexBase + 0) = "Do you think you should be able to*?" +4260 LET replies(6)(indexBase + 1) = "Why can't you*?" +4270 REM TODO: Check indexBase value (automatically generated) +4280 LET indexBase = 0 +4290 LET replies(7)(indexBase + 0) = "Why are you interested in whether or not I am*?" +4300 LET replies(7)(indexBase + 1) = "Would you prefer if I were not*?" +4310 LET replies(7)(indexBase + 2) = "Perhaps in your fantasies I am*?" +4320 REM TODO: Check indexBase value (automatically generated) +4330 LET indexBase = 0 +4340 LET replies(8)(indexBase + 0) = "How do you know you can't*?" +4350 LET replies(8)(indexBase + 1) = "Have you tried?" +4360 LET replies(8)(indexBase + 2) = "Perhaps you can now*." +4370 REM TODO: Check indexBase value (automatically generated) +4380 LET indexBase = 0 +4390 LET replies(9)(indexBase + 0) = "Did you come to me because you are*?" +4400 LET replies(9)(indexBase + 1) = "How long have you been*?" +4410 LET replies(9)(indexBase + 2) = "Do you believe it is normal to be*?" +4420 LET replies(9)(indexBase + 3) = "Do you enjoy being*?" +4430 REM TODO: Check indexBase value (automatically generated) +4440 LET indexBase = 0 +4450 LET replies(10)(indexBase + 0) = "We were discussing you--not me." +4460 LET replies(10)(indexBase + 1) = "Oh, I*." +4470 LET replies(10)(indexBase + 2) = "You're not really talking about me, are you?" +4480 REM TODO: Check indexBase value (automatically generated) +4490 LET indexBase = 0 +4500 LET replies(11)(indexBase + 0) = "What would it mean to you if you got*?" +4510 LET replies(11)(indexBase + 1) = "Why do you want*?" +4520 LET replies(11)(indexBase + 2) = "Suppose you soon got*..." +4530 LET replies(11)(indexBase + 3) = "What if you never got*?" +4540 LET replies(11)(indexBase + 4) = "I sometimes also want*." +4550 REM TODO: Check indexBase value (automatically generated) +4560 LET indexBase = 0 +4570 LET replies(12)(indexBase + 0) = "Why do you ask?" +4580 LET replies(12)(indexBase + 1) = "Does that question interest you?" +4590 LET replies(12)(indexBase + 2) = "What answer would please you the most?" +4600 LET replies(12)(indexBase + 3) = "What do you think?" +4610 LET replies(12)(indexBase + 4) = "Are such questions on your mind often?" +4620 LET replies(12)(indexBase + 5) = "What is it that you really want to know?" +4630 LET replies(12)(indexBase + 6) = "Have you asked anyone else?" +4640 LET replies(12)(indexBase + 7) = "Have you asked such questions before?" +4650 LET replies(12)(indexBase + 8) = "What else comes to mind when you ask that?" +4660 REM TODO: Check indexBase value (automatically generated) +4670 LET indexBase = 0 +4680 LET replies(13)(indexBase + 0) = "Names don't interest me." +4690 LET replies(13)(indexBase + 1) = "I don't care about names -- please go on." +4700 REM TODO: Check indexBase value (automatically generated) +4710 LET indexBase = 0 +4720 LET replies(14)(indexBase + 0) = "Is that the real reason?" +4730 LET replies(14)(indexBase + 1) = "Don't any other reasons come to mind?" +4740 LET replies(14)(indexBase + 2) = "Does that reason explain anything else?" +4750 LET replies(14)(indexBase + 3) = "What other reasons might there be?" +4760 REM TODO: Check indexBase value (automatically generated) +4770 LET indexBase = 0 +4780 LET replies(15)(indexBase + 0) = "Please don't apologize!" +4790 LET replies(15)(indexBase + 1) = "Apologies are not necessary." +4800 LET replies(15)(indexBase + 2) = "What feelings do you have when you apologize?" +4810 LET replies(15)(indexBase + 3) = "Don't be so defensive!" +4820 REM TODO: Check indexBase value (automatically generated) +4830 LET indexBase = 0 +4840 LET replies(16)(indexBase + 0) = "What does that dream suggest to you?" +4850 LET replies(16)(indexBase + 1) = "Do you dream often?" +4860 LET replies(16)(indexBase + 2) = "What persons appear in your dreams?" +4870 LET replies(16)(indexBase + 3) = "Are you disturbed by your dreams?" +4880 REM TODO: Check indexBase value (automatically generated) +4890 LET indexBase = 0 +4900 LET replies(17)(indexBase + 0) = "How do you do ...please state your problem." +4910 REM TODO: Check indexBase value (automatically generated) +4920 LET indexBase = 0 +4930 LET replies(18)(indexBase + 0) = "You don't seem quite certain." +4940 LET replies(18)(indexBase + 1) = "Why the uncertain tone?" +4950 LET replies(18)(indexBase + 2) = "Can't you be more positive?" +4960 LET replies(18)(indexBase + 3) = "You aren't sure?" +4970 LET replies(18)(indexBase + 4) = "Don't you know?" +4980 REM TODO: Check indexBase value (automatically generated) +4990 LET indexBase = 0 +5000 LET replies(19)(indexBase + 0) = "Are you saying no just to be negative?" +5010 LET replies(19)(indexBase + 1) = "You are being a bit negative." +5020 LET replies(19)(indexBase + 2) = "Why not?" +5030 LET replies(19)(indexBase + 3) = "Are you sure?" +5040 LET replies(19)(indexBase + 4) = "Why no?" +5050 REM TODO: Check indexBase value (automatically generated) +5060 LET indexBase = 0 +5070 LET replies(20)(indexBase + 0) = "Why are you concerned about my*?" +5080 LET replies(20)(indexBase + 1) = "What about your own*?" +5090 REM TODO: Check indexBase value (automatically generated) +5100 LET indexBase = 0 +5110 LET replies(21)(indexBase + 0) = "Can you think of a specific example?" +5120 LET replies(21)(indexBase + 1) = "When?" +5130 LET replies(21)(indexBase + 2) = "What are you thinking of?" +5140 LET replies(21)(indexBase + 3) = "Really, always?" +5150 REM TODO: Check indexBase value (automatically generated) +5160 LET indexBase = 0 +5170 LET replies(22)(indexBase + 0) = "Do you really think so?" +5180 LET replies(22)(indexBase + 1) = "But you are not sure you*?" +5190 LET replies(22)(indexBase + 2) = "Do you doubt you*?" +5200 REM TODO: Check indexBase value (automatically generated) +5210 LET indexBase = 0 +5220 LET replies(23)(indexBase + 0) = "In what way?" +5230 LET replies(23)(indexBase + 1) = "What resemblance do you see?" +5240 LET replies(23)(indexBase + 2) = "What does the similarity suggest to you?" +5250 LET replies(23)(indexBase + 3) = "What other connections do you see?" +5260 LET replies(23)(indexBase + 4) = "Could there really be some connection?" +5270 LET replies(23)(indexBase + 5) = "How?" +5280 LET replies(23)(indexBase + 6) = "You seem quite positive." +5290 REM TODO: Check indexBase value (automatically generated) +5300 LET indexBase = 0 +5310 LET replies(24)(indexBase + 0) = "Are you sure?" +5320 LET replies(24)(indexBase + 1) = "I see." +5330 LET replies(24)(indexBase + 2) = "I understand." +5340 REM TODO: Check indexBase value (automatically generated) +5350 LET indexBase = 0 +5360 LET replies(25)(indexBase + 0) = "Why do you bring up the topic of friends?" +5370 LET replies(25)(indexBase + 1) = "Do your friends worry you?" +5380 LET replies(25)(indexBase + 2) = "Do your friends pick on you?" +5390 LET replies(25)(indexBase + 3) = "Are you sure you have any friends?" +5400 LET replies(25)(indexBase + 4) = "Do you impose on your friends?" +5410 LET replies(25)(indexBase + 5) = "Perhaps your love for friends worries you." +5420 REM TODO: Check indexBase value (automatically generated) +5430 LET indexBase = 0 +5440 LET replies(26)(indexBase + 0) = "Do computers worry you?" +5450 LET replies(26)(indexBase + 1) = "Are you talking about me in particular?" +5460 LET replies(26)(indexBase + 2) = "Are you frightened by machines?" +5470 LET replies(26)(indexBase + 3) = "Why do you mention computers?" +5480 LET replies(26)(indexBase + 4) = "What do you think machines have to do with your problem?" +5490 LET replies(26)(indexBase + 5) = "Don't you think computers can help people?" +5500 LET replies(26)(indexBase + 6) = "What is it about machines that worries you?" +5510 REM TODO: Check indexBase value (automatically generated) +5520 LET indexBase = 0 +5530 LET replies(27)(indexBase + 0) = "Do you sometimes feel uneasy without a smartphone?" +5540 LET replies(27)(indexBase + 1) = "Have you had these phantasies before?" +5550 LET replies(27)(indexBase + 2) = "Does the world seem more real for you via apps?" +5560 REM TODO: Check indexBase value (automatically generated) +5570 LET indexBase = 0 +5580 LET replies(28)(indexBase + 0) = "Tell me more about your family." +5590 LET replies(28)(indexBase + 1) = "Who else in your family*?" +5600 LET replies(28)(indexBase + 2) = "What does family relations mean for you?" +5610 LET replies(28)(indexBase + 3) = "Come on, How old are you?" +5620 LET setupReplies = replies +5630 RETURN setupReplies +5640 END FUNCTION diff --git a/samples/export/BASIC0/SORTING_TEST_MAIN.bas b/samples/export/BASIC0/SORTING_TEST_MAIN.bas index 21cf6415..fec0bd0d 100644 --- a/samples/export/BASIC0/SORTING_TEST_MAIN.bas +++ b/samples/export/BASIC0/SORTING_TEST_MAIN.bas @@ -2,7 +2,7 @@ 20 REM to allow performance comparison via execution counting ("Collect Runtime Data" should 30 REM sensibly be switched on). 40 REM Requested input data are: Number of elements (size) and filing mode. -50 REM Generated by Structorizer 3.30-02 +50 REM Generated by Structorizer 3.30-03 60 REM 70 REM Copyright (C) 2019-10-02 Kay Gürtzig 80 REM License: GPLv3-link @@ -29,7 +29,7 @@ 290 LET values1(i) = -i 300 END SELECT 310 NEXT i -320 REM Kopiere das Array für exakte Vergleichbarkeit +320 REM Copy the array for exact comparability 330 FOR i = 0 TO elementCount-1 340 LET values2(i) = values1(i) 350 LET values3(i) = values1(i) @@ -58,9 +58,9 @@ 580 REM ================== END PARALLEL SECTION ================== 590 REM ========================================================== 600 -610 LET CALL ok1 = testSorted(values1) -620 LET CALL ok2 = testSorted(values2) -630 LET CALL ok3 = testSorted(values3) +610 LET ok1 = testSorted(values1) +620 LET ok2 = testSorted(values2) +630 LET ok3 = testSorted(values3) 640 IF NOT ok1 OR NOT ok2 OR NOT ok3 THEN 650 FOR i = 0 TO elementCount-1 660 IF values1(i) <> values2(i) OR values1(i) <> values3(i) THEN @@ -212,7 +212,7 @@ 2120 LET p = random(stop-start) + start 2130 REM Partition the array into smaller and greater elements 2140 REM Get the resulting (and final) position of the pivot element -2150 LET CALL p = partition(values, start, stop, p) +2150 LET p = partition(values, start, stop, p) 2160 REM Sort subsequances separately and independently ... 2170 2180 REM ========================================================== diff --git a/samples/export/BASIC0/TextDemo.bas b/samples/export/BASIC0/TextDemo.bas new file mode 100644 index 00000000..c36e6f08 --- /dev/null +++ b/samples/export/BASIC0/TextDemo.bas @@ -0,0 +1,1006 @@ +10 REM Demo program for routine drawText() +20 REM Asks the user to enter a text, a wanted text height and colour, +30 REM and then draws this string onto the turtle screen. Places every +40 REM entered text to a new line. +50 REM Generated by Structorizer 3.30-03 +60 REM +70 REM Copyright (C) 2019-10-10 Kay Gürtzig +80 REM License: GPLv3-link +90 REM GNU General Public License (V 3) +100 REM https://www.gnu.org/licenses/gpl.html +110 REM http://www.gnu.de/documents/gpl.de.html +120 REM +130 REM +140 REM program TextDemo +150 REM TODO: add the respective type suffixes to your variable names if required +160 PRINT "This is a demo program for text writing with Turleizer." +170 showTurtle() +180 penDown() +190 LET y = 0 +200 DO +210 PRINT "Enter some text (empty string to exit)"; : INPUT text +220 REM Make sure the content is interpreted as string +230 LET text = "" + text +240 IF text <> "" THEN +250 DO +260 PRINT "Height of the text (pixels)"; : INPUT height +270 LOOP UNTIL height >= 5 +280 DO +290 PRINT "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"; : INPUT colour +300 LOOP UNTIL colour >= 1 AND colour <= 10 +310 LET y = y + height + 2 +320 gotoXY(0, y - 2) +330 CALL drawText(text, height, colour) +340 END IF +350 LOOP UNTIL text = "" +360 gotoXY(0, y + 15) +370 CALL drawText("Thank you, bye.", 10, 4) +380 hideTurtle() +390 END +400 REM +410 REM Draws a blank for font height h, ignoring the colorNo +420 REM TODO: Add type-specific suffixes where necessary! +430 SUB blank(h, colorNo) +440 REM TODO: add the respective type suffixes to your variable names if required +450 LET width = h/2.0 +460 penUp() +470 right(90) +480 forward(width) : REM color = ffffff +490 left(90) +500 END SUB +510 REM +520 REM TODO: Add type-specific suffixes where necessary! +530 SUB forward(len, color) +540 REM TODO: add the respective type suffixes to your variable names if required +550 SELECT CASE color +560 CASE 1 +570 forward(len) : REM color = ffffff +580 CASE 2 +590 forward(len) : REM color = ff8080 +600 CASE 3 +610 forward(len) : REM color = ffff80 +620 CASE 4 +630 forward(len) : REM color = 80ff80 +640 CASE 5 +650 forward(len) : REM color = 80ffff +660 CASE 6 +670 forward(len) : REM color = 0080ff +680 CASE 7 +690 forward(len) : REM color = ff80c0 +700 CASE 8 +710 forward(len) : REM color = c0c0c0 +720 CASE 9 +730 forward(len) : REM color = ff8000 +740 CASE 10 +750 forward(len) : REM color = 8080ff +760 END SELECT +770 END SUB +780 REM +790 REM Draws letter A in colour specified by colorNo with font height h +800 REM from the current turtle position. +810 REM TODO: Add type-specific suffixes where necessary! +820 SUB letterA(h, colorNo) +830 REM TODO: add the respective type suffixes to your variable names if required +840 LET width = h/2.0 +850 LET hypo = sqrt(h*h + width*width/4.0) +860 LET rotAngle = toDegrees(atan(width/2.0/h)) +870 right(rotAngle) +880 CALL forward(hypo/2.0, colorNo) +890 right(90 - rotAngle) +900 CALL forward(width/2.0, colorNo) +910 penUp() +920 backward(width/2.0) : REM color = ffffff +930 penDown() +940 left(90 - rotAngle) +950 CALL forward(hypo/2.0, colorNo) +960 left(2*rotAngle) +970 CALL forward(-hypo, colorNo) +980 right(rotAngle) +990 END SUB +1000 REM +1010 REM Draws letter E in colour specified by colorNo with font height h +1020 REM from the current turtle position. +1030 REM TODO: Add type-specific suffixes where necessary! +1040 SUB letterE(h, colorNo) +1050 REM TODO: add the respective type suffixes to your variable names if required +1060 LET width = h/2.0 +1070 CALL forward(h, colorNo) +1080 right(90) +1090 CALL forward(width, colorNo) +1100 right(90) +1110 penUp() +1120 forward(h/2.0) : REM color = ffffff +1130 right(90) +1140 penDown() +1150 CALL forward(width, colorNo) +1160 left(90) +1170 penUp() +1180 forward(h/2.0) : REM color = ffffff +1190 left(90) +1200 penDown() +1210 CALL forward(width, colorNo) +1220 left(90) +1230 END SUB +1240 REM +1250 REM Draws letter F in colour specified by colorNo with font height h +1260 REM from the current turtle position. +1270 REM TODO: Add type-specific suffixes where necessary! +1280 SUB letterF(h, colorNo) +1290 REM TODO: add the respective type suffixes to your variable names if required +1300 LET width = h/2.0 +1310 CALL forward(h, colorNo) +1320 right(90) +1330 CALL forward(width, colorNo) +1340 right(90) +1350 penUp() +1360 forward(h/2.0) : REM color = ffffff +1370 right(90) +1380 penDown() +1390 CALL forward(width, colorNo) +1400 left(90) +1410 penUp() +1420 forward(h/2.0) : REM color = ffffff +1430 left(90) +1440 forward(width) : REM color = ffffff +1450 penDown() +1460 left(90) +1470 END SUB +1480 REM +1490 REM Draws letter H in colour specified by colorNo with font height h +1500 REM from the current turtle position. +1510 REM TODO: Add type-specific suffixes where necessary! +1520 SUB letterH(h, colorNo) +1530 REM TODO: add the respective type suffixes to your variable names if required +1540 LET width = h/2.0 +1550 CALL forward(h, colorNo) +1560 penUp() +1570 right(90) +1580 forward(width) : REM color = ffffff +1590 right(90) +1600 penDown() +1610 CALL forward(h/2.0, colorNo) +1620 right(90) +1630 CALL forward(width, colorNo) +1640 penUp() +1650 backward(width) : REM color = ffffff +1660 left(90) +1670 penDown() +1680 CALL forward(h/2.0, colorNo) +1690 left(180) +1700 END SUB +1710 REM +1720 REM Draws letter I in colour specified by colorNo with font height h +1730 REM from the current turtle position. +1740 REM TODO: Add type-specific suffixes where necessary! +1750 SUB letterI(h, colorNo) +1760 REM TODO: add the respective type suffixes to your variable names if required +1770 REM Octagon edge length +1780 LET b = h * 0.5 / (sqrt(2.0) + 1) +1790 REM Cathetus of the corner triangle outside the octagon +1800 LET c = b / sqrt(2.0) +1810 penUp() +1820 right(90) +1830 forward(c) : REM color = ffffff +1840 penDown() +1850 CALL forward(b, colorNo) +1860 penUp() +1870 backward(b/2.0) : REM color = ffffff +1880 left(90) +1890 penDown() +1900 CALL forward(h, colorNo) +1910 penUp() +1920 right(90) +1930 backward(b/2.0) : REM color = ffffff +1940 penDown() +1950 CALL forward(b, colorNo) +1960 penUp() +1970 forward(b/2 + c) : REM color = ffffff +1980 left(90) +1990 backward(h) : REM color = ffffff +2000 penDown() +2010 END SUB +2020 REM +2030 REM Draws letter K in colour specified by colorNo with font height h +2040 REM from the current turtle position. +2050 REM TODO: Add type-specific suffixes where necessary! +2060 SUB letterK(h, colorNo) +2070 REM TODO: add the respective type suffixes to your variable names if required +2080 LET width = h/2.0 +2090 LET diag = h/sqrt(2.0) +2100 CALL forward(h, colorNo) +2110 penUp() +2120 right(90) +2130 forward(width) : REM color = ffffff +2140 right(135) +2150 penDown() +2160 CALL forward(diag, colorNo) +2170 left(90) +2180 CALL forward(diag, colorNo) +2190 left(135) +2200 END SUB +2210 REM +2220 REM Draws letter L in colour specified by colorNo with font height h +2230 REM from the current turtle position. +2240 REM TODO: Add type-specific suffixes where necessary! +2250 SUB letterL(h, colorNo) +2260 REM TODO: add the respective type suffixes to your variable names if required +2270 LET width = h/2.0 +2280 CALL forward(h, colorNo) +2290 penUp() +2300 backward(h) : REM color = ffffff +2310 right(90) +2320 penDown() +2330 CALL forward(width, colorNo) +2340 left(90) +2350 END SUB +2360 REM +2370 REM Draws letter M in colour specified by colorNo with font height h +2380 REM from the current turtle position. +2390 REM TODO: Add type-specific suffixes where necessary! +2400 SUB letterM(h, colorNo) +2410 REM TODO: add the respective type suffixes to your variable names if required +2420 LET width = h/2.0 +2430 LET hypo = sqrt(width*width + h*h)/2.0 +2440 LET rotAngle = toDegrees(atan(width/h)) +2450 CALL forward(h, colorNo) +2460 left(rotAngle) +2470 CALL forward(-hypo, colorNo) +2480 right(2*rotAngle) +2490 CALL forward(hypo, colorNo) +2500 left(rotAngle) +2510 CALL forward(-h, colorNo) +2520 END SUB +2530 REM +2540 REM Draws letter N in colour specified by colorNo with font height h +2550 REM from the current turtle position. +2560 REM TODO: Add type-specific suffixes where necessary! +2570 SUB letterN(h, colorNo) +2580 REM TODO: add the respective type suffixes to your variable names if required +2590 LET width = h/2.0 +2600 LET hypo = sqrt(width*width + h*h) +2610 LET rotAngle = toDegrees(atan(width/h)) +2620 CALL forward(h, colorNo) +2630 left(rotAngle) +2640 CALL forward(-hypo, colorNo) +2650 right(rotAngle) +2660 CALL forward(h, colorNo) +2670 penUp() +2680 backward(h) : REM color = ffffff +2690 penDown() +2700 END SUB +2710 REM +2720 REM Draws letter T in colour specified by colorNo with font height h +2730 REM from the current turtle position. +2740 REM TODO: Add type-specific suffixes where necessary! +2750 SUB letterT(h, colorNo) +2760 REM TODO: add the respective type suffixes to your variable names if required +2770 LET width = h/2.0 +2780 penUp() +2790 forward(h) : REM color = ffffff +2800 penDown() +2810 right(90) +2820 CALL forward(width, colorNo) +2830 penUp() +2840 backward(width/2.0) : REM color = ffffff +2850 penDown() +2860 right(90) +2870 CALL forward(h, colorNo) +2880 left(90) +2890 penUp() +2900 forward(width/2.0) : REM color = ffffff +2910 penDown() +2920 left(90) +2930 END SUB +2940 REM +2950 REM Draws letter V in colour specified by colorNo with font height h +2960 REM from the current turtle position. +2970 REM TODO: Add type-specific suffixes where necessary! +2980 SUB letterV(h, colorNo) +2990 REM TODO: add the respective type suffixes to your variable names if required +3000 LET width = h/2.0 +3010 LET hypo = sqrt(h*h + width*width/4.0) +3020 LET rotAngle = toDegrees(atan(width/2.0/h)) +3030 penUp() +3040 forward(h) : REM color = ffffff +3050 left(rotAngle) +3060 penDown() +3070 CALL forward(-hypo, colorNo) +3080 right(2*rotAngle) +3090 CALL forward(hypo, colorNo) +3100 penUp() +3110 left(rotAngle) +3120 backward(h) : REM color = ffffff +3130 penDown() +3140 END SUB +3150 REM +3160 REM Draws letter W in colour specified by colorNo with font height h +3170 REM from the current turtle position. +3180 REM TODO: Add type-specific suffixes where necessary! +3190 SUB letterW(h, colorNo) +3200 REM TODO: add the respective type suffixes to your variable names if required +3210 LET width = h/2.0 +3220 LET width_3 = width/3.0 +3230 LET hypo = sqrt(width_3*width_3 + h*h) +3240 LET rotAngle = toDegrees(atan(width_3/h)) +3250 penUp() +3260 forward(h) : REM color = ffffff +3270 left(rotAngle) +3280 penDown() +3290 CALL forward(-hypo, colorNo) +3300 right(2*rotAngle) +3310 CALL forward(hypo, colorNo) +3320 penUp() +3330 left(90+rotAngle) +3340 forward(width_3) : REM color = ffffff +3350 right(90-rotAngle) +3360 penDown() +3370 CALL forward(-hypo, colorNo) +3380 right(2*rotAngle) +3390 CALL forward(hypo, colorNo) +3400 penUp() +3410 left(rotAngle) +3420 backward(h) : REM color = ffffff +3430 penDown() +3440 END SUB +3450 REM +3460 REM Draws letter X in colour specified by colorNo with font height h +3470 REM from the current turtle position. +3480 REM TODO: Add type-specific suffixes where necessary! +3490 SUB letterX(h, colorNo) +3500 REM TODO: add the respective type suffixes to your variable names if required +3510 LET width = h/2.0 +3520 LET hypo = sqrt(width*width + h*h) +3530 LET rotAngle = toDegrees(atan(width/h)) +3540 right(rotAngle) +3550 CALL forward(hypo, colorNo) +3560 penUp() +3570 left(90+rotAngle) +3580 forward(width) : REM color = ffffff +3590 right(90-rotAngle) +3600 penDown() +3610 CALL forward(-hypo, colorNo) +3620 right(rotAngle) +3630 END SUB +3640 REM +3650 REM Draws letter Y in colour specified by colorNo with font height h +3660 REM from the current turtle position. +3670 REM TODO: Add type-specific suffixes where necessary! +3680 SUB letterY(h, colorNo) +3690 REM TODO: add the respective type suffixes to your variable names if required +3700 LET width = h/2.0 +3710 LET hypo = sqrt(width*width + h*h)/2.0 +3720 LET rotAngle = toDegrees(atan(width/h)) +3730 penUp() +3740 forward(h) : REM color = ffffff +3750 left(rotAngle) +3760 penDown() +3770 CALL forward(-hypo, colorNo) +3780 right(rotAngle) +3790 penUp() +3800 backward(h/2.0) : REM color = ffffff +3810 penDown() +3820 CALL forward(h/2.0, colorNo) +3830 right(rotAngle) +3840 CALL forward(hypo, colorNo) +3850 left(rotAngle) +3860 penUp() +3870 backward(h) : REM color = ffffff +3880 penDown() +3890 END SUB +3900 REM +3910 REM Draws letter Z in colour specified by colorNo with font height h +3920 REM from the current turtle position. +3930 REM TODO: Add type-specific suffixes where necessary! +3940 SUB letterZ(h, colorNo) +3950 REM TODO: add the respective type suffixes to your variable names if required +3960 LET width = h/2.0 +3970 LET hypo = sqrt(width*width + h*h) +3980 LET rotAngle = toDegrees(atan(width/h)) +3990 penUp() +4000 forward(h) : REM color = ffffff +4010 right(90) +4020 penDown() +4030 CALL forward(width, colorNo) +4040 left(90-rotAngle) +4050 CALL forward(-hypo, colorNo) +4060 right(90-rotAngle) +4070 CALL forward(width, colorNo) +4080 left(90) +4090 END SUB +4100 REM +4110 REM Draws nEdges edges of a regular n-polygon with edge length a +4120 REM counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +4130 REM TODO: Add type-specific suffixes where necessary! +4140 SUB polygonPart(a AS double, n AS integer, ctrclkws AS boolean, nEdges AS integer, color AS Integer) +4150 REM TODO: add the respective type suffixes to your variable names if required +4160 LET rotAngle = 360.0/n +4170 IF ctrclkws THEN +4180 LET rotAngle = -rotAngle +4190 END IF +4200 FOR k = 1 TO nEdges +4210 right(rotAngle) +4220 CALL forward(a, color) +4230 NEXT k +4240 END SUB +4250 REM +4260 REM Draws a dummy character (small centered square) with font height h and +4270 REM the colour encoded by colorNo +4280 REM TODO: Add type-specific suffixes where necessary! +4290 SUB charDummy(h, colorNo) +4300 REM TODO: add the respective type suffixes to your variable names if required +4310 LET width = h / 2.0 +4320 REM Octagon edge length (here: edge lengzh of the square) +4330 LET b = width / (sqrt(2.0) + 1) +4340 REM Cathetus of the corner triangle outside the octagon +4350 LET c = (width - b) / 2.0 +4360 LET d = b / sqrt(2.0) +4370 penUp() +4380 forward(h/2.0-b/2.0) : REM color = ffffff +4390 right(90) +4400 forward(c) : REM color = ffffff +4410 right(90) +4420 penDown() +4430 REM Draws the square with edge length b +4440 CALL polygonPart(b, 4, true, 4, colorNo) +4450 penUp() +4460 left(90) +4470 forward(b + c) : REM color = ffffff +4480 left(90) +4490 backward(h/2.0-b/2.0) : REM color = ffffff +4500 penDown() +4510 END SUB +4520 REM +4530 REM Draws a comma in colour specified by colorNo with font height h +4540 REM from the current turtle position. +4550 REM TODO: Add type-specific suffixes where necessary! +4560 SUB comma(h, colorNo) +4570 REM TODO: add the respective type suffixes to your variable names if required +4580 REM Achteck-Kantenlänge +4590 LET b = h * 0.5 / (sqrt(2.0) + 1) +4600 REM Eckenlänge außen am Achteck +4610 LET c = b / sqrt(2.0) +4620 LET rotAngle = toDegrees(atan(0.5)) +4630 LET hypo = c * sqrt(1.25) +4640 penUp() +4650 right(90) +4660 forward((c+b)/2.0 + c) : REM color = ffffff +4670 penDown() +4680 REM Counterclockwise draw 3 edges of a square with edge length c +4690 REM in the colour endcoded by colorNo +4700 CALL polygonPart(c, 4, true, 3, colorNo) +4710 left(90) +4720 CALL forward(c/2.0, colorNo) +4730 right(90) +4740 CALL forward(c, colorNo) +4750 left(180 - rotAngle) +4760 CALL forward(hypo, colorNo) +4770 penUp() +4780 right(90 - rotAngle) +4790 forward((c + b)/2.0) : REM color = ffffff +4800 left(90) +4810 penDown() +4820 END SUB +4830 REM +4840 REM Draws an exclamation mark in the colour encoded by colorNo with font height h +4850 REM from the current turtle position. +4860 REM TODO: Add type-specific suffixes where necessary! +4870 SUB exclMk(h, colorNo) +4880 REM TODO: add the respective type suffixes to your variable names if required +4890 REM Achteck-Kantenlänge +4900 LET b = h * 0.5 / (sqrt(2.0) + 1) +4910 REM Eckenlänge außen am Achteck +4920 LET c = b / sqrt(2.0) +4930 LET width = h/2.0 +4940 LET length1 = h - (b+c)/2.0 +4950 LET length2 = length1 - 2*c +4960 LET hypo = sqrt(width*width/16.0 + length2*length2) +4970 REM 360°/8 +4980 LET rotAngle = 45 +4990 LET rotAngle2 = toDegrees(atan(width/4.0/length2)) +5000 penUp() +5010 forward(length1) : REM color = ffffff +5020 right(90) +5030 forward(width/2.0) : REM color = ffffff +5040 left(90 + rotAngle) +5050 penDown() +5060 REM Clockwise draw 5 edges of an octagon with edge length b/2 +5070 REM in the colour endcoded by colorNo +5080 CALL polygonPart(b/2.0, 8, false, 5, colorNo) +5090 right(rotAngle2) +5100 CALL forward(hypo, colorNo) +5110 left(2*rotAngle2) +5120 CALL forward(-hypo, colorNo) +5130 penUp() +5140 forward(hypo) : REM color = ffffff +5150 right(rotAngle2) +5160 forward(c) : REM color = ffffff +5170 left(90) +5180 forward(c/2.0) : REM color = ffffff +5190 penDown() +5200 REM Counterclockwise draw all 4 edges of a squarfe with edge length c +5210 REM in the colour endcoded by colorNo +5220 CALL polygonPart(c, 4, false, 4, colorNo) +5230 penUp() +5240 forward((c + b)/2.0) : REM color = ffffff +5250 left(90) +5260 backward(c) : REM color = ffffff +5270 penDown() +5280 END SUB +5290 REM +5300 REM Draws a full stop in colour specified by colorNo with font height h +5310 REM from the current turtle position. +5320 REM TODO: Add type-specific suffixes where necessary! +5330 SUB fullSt(h, colorNo) +5340 REM TODO: add the respective type suffixes to your variable names if required +5350 REM Achteck-Kantenlänge +5360 LET b = h * 0.5 / (sqrt(2.0) + 1) +5370 REM Eckenlänge außen am Achteck +5380 LET c = b / sqrt(2.0) +5390 penUp() +5400 right(90) +5410 forward((c+b)/2.0 + c) : REM color = ffffff +5420 penDown() +5430 REM Counterclockwise draw all 4 edges of a squarfe with edge length c +5440 REM in the colour endcoded by colorNo +5450 CALL polygonPart(c, 4, true, 4, colorNo) +5460 penUp() +5470 forward((c + b)/2.0) : REM color = ffffff +5480 left(90) +5490 penDown() +5500 END SUB +5510 REM +5520 REM Draws letter B in colour specified by colorNo with font height h +5530 REM from the current turtle position. +5540 REM TODO: Add type-specific suffixes where necessary! +5550 SUB letterB(h, colorNo) +5560 REM TODO: add the respective type suffixes to your variable names if required +5570 REM Octagon edge length +5580 LET b = h * 0.5 / (sqrt(2.0) + 1) +5590 REM Cathetus of the outer corner triangle of the octagon +5600 LET c = b / sqrt(2.0) +5610 CALL forward(h, colorNo) +5620 right(90) +5630 CALL forward(c+b, colorNo) +5640 REM Clockwise draw 4 edges of an octagon with edge length b +5650 CALL polygonPart(b, 8, false, 4, colorNo) +5660 CALL forward(c, colorNo) +5670 penUp() +5680 left(180) +5690 forward(b + c) : REM color = ffffff +5700 penDown() +5710 REM Clockwise draw 4 edges of an octagon with edge length b +5720 CALL polygonPart(b, 8, false, 4, colorNo) +5730 CALL forward(c, colorNo) +5740 penUp() +5750 left(180) +5760 forward(b + 2*c) : REM color = ffffff +5770 penDown() +5780 left(90) +5790 END SUB +5800 REM +5810 REM Draws letter C in the colour encoded by colorNo with font height h +5820 REM from the current turtle position. +5830 REM TODO: Add type-specific suffixes where necessary! +5840 SUB letterC(h, colorNo) +5850 REM TODO: add the respective type suffixes to your variable names if required +5860 REM Octagon edge length +5870 LET b = h * 0.5 / (sqrt(2.0) + 1) +5880 REM Cathetus of the outer trinagle at the octagon corner +5890 LET c = b / sqrt(2.0) +5900 REM 360°/8 +5910 LET rotAngle = 45 +5920 penUp() +5930 forward(c) : REM color = ffffff +5940 penDown() +5950 right(180) +5960 REM Clockwise draws 3 edges of an octagon with edge length b in the colour +5970 REM encoded by colorNo +5980 CALL polygonPart(b, 8, true, 3, colorNo) +5990 left(rotAngle) +6000 penUp() +6010 forward(2*b + 2*c) : REM color = ffffff +6020 penDown() +6030 REM Counterclockwise draws 4 edges of an octagon with edge length b +6040 REM iin the colour encoded by colorNo +6050 CALL polygonPart(b, 8, true, 4, colorNo) +6060 CALL forward(b + 2*c, colorNo) +6070 penUp() +6080 forward(c) : REM color = ffffff +6090 left(90) +6100 CALL forward(b + 2*c, colorNo) +6110 penDown() +6120 left(90) +6130 END SUB +6140 REM +6150 REM Draws letter D in colour specified by colorNo with font height h +6160 REM from the current turtle position. +6170 REM TODO: Add type-specific suffixes where necessary! +6180 SUB letterD(h, colorNo) +6190 REM TODO: add the respective type suffixes to your variable names if required +6200 REM Achteck-Kantenlänge +6210 LET b = h * 0.5 / (sqrt(2.0) + 1) +6220 REM Eckenlänge außen am Achteck +6230 LET c = b / sqrt(2.0) +6240 CALL forward(h, colorNo) +6250 right(90) +6260 CALL forward(c+b, colorNo) +6270 REM Clockwise draw 2 edges of an octagon with edge length b in the colour +6280 REM encoded by colorNo +6290 CALL polygonPart(b, 8, false, 2, colorNo) +6300 CALL forward(b + 2*c, colorNo) +6310 REM Clockwise draw 2 edges of an octagon with edge length b in the colour +6320 REM encoded by colorNo +6330 CALL polygonPart(b, 8, false, 2, colorNo) +6340 CALL forward(c, colorNo) +6350 penUp() +6360 left(180) +6370 forward(b + 2*c) : REM color = ffffff +6380 penDown() +6390 left(90) +6400 END SUB +6410 REM +6420 REM Draws letter G in colour specified by colorNo with font height h +6430 REM from the current turtle position. +6440 REM TODO: Add type-specific suffixes where necessary! +6450 SUB letterG(h, colorNo) +6460 REM TODO: add the respective type suffixes to your variable names if required +6470 REM Octagon edge length +6480 LET b = h * 0.5 / (sqrt(2.0) + 1) +6490 REM Cathetus of the corner triangle outside the octagon. +6500 LET c = b / sqrt(2.0) +6510 penUp() +6520 forward(c) : REM color = ffffff +6530 penDown() +6540 right(180) +6550 REM Counterclockwise draw 4 edges of an octagon with edge length b in +6560 REM the colour encoded by colorNo +6570 CALL polygonPart(b, 8, true, 4, colorNo) +6580 CALL forward(c, colorNo) +6590 left(90) +6600 CALL forward(b/2.0 + c, colorNo) +6610 penUp() +6620 backward(b/2.0 + c) : REM color = ffffff +6630 right(90) +6640 forward(b + c) : REM color = ffffff +6650 penDown() +6660 REM Counterclockwise draw 4 edges of an octagon with edge length b in +6670 REM the colour encoded by colorNo +6680 CALL polygonPart(b, 8, true, 4, colorNo) +6690 CALL forward(b + 2*c, colorNo) +6700 penUp() +6710 forward(c) : REM color = ffffff +6720 left(90) +6730 CALL forward(b + 2*c, colorNo) +6740 penDown() +6750 left(90) +6760 END SUB +6770 REM +6780 REM Draws letter J in colour encoded by colorNo with font height h +6790 REM from the current turtle position. +6800 REM TODO: Add type-specific suffixes where necessary! +6810 SUB letterJ(h, colorNo) +6820 REM TODO: add the respective type suffixes to your variable names if required +6830 REM Achteck-Kantenlänge +6840 LET b = h * 0.5 / (sqrt(2.0) + 1) +6850 REM Eckenlänge außen am Achteck +6860 LET c = b / sqrt(2.0) +6870 REM 360°/8 +6880 LET rotAngle = 45 +6890 penUp() +6900 forward(c) : REM color = ffffff +6910 penDown() +6920 right(180) +6930 REM Counterclockwise draw 3 edges of an octagon with edge length b in +6940 REM the colour encoded by colorNo +6950 CALL polygonPart(b, 8, true, 3, colorNo) +6960 left(rotAngle) +6970 CALL forward(h - c, colorNo) +6980 penUp() +6990 backward(h) : REM color = ffffff +7000 penDown() +7010 END SUB +7020 REM +7030 REM Draws letter O in colour specified by colorNo with font height h +7040 REM from the current turtle position. +7050 REM TODO: Add type-specific suffixes where necessary! +7060 SUB letterO(h, colorNo) +7070 REM TODO: add the respective type suffixes to your variable names if required +7080 REM Octagon edge length +7090 LET b = h * 0.5 / (sqrt(2.0) + 1) +7100 REM Cathetus of the corner triangle outside the octagon +7110 LET c = b / sqrt(2.0) +7120 penUp() +7130 forward(c) : REM color = ffffff +7140 penDown() +7150 right(180) +7160 REM Counterclockwise draw 4 edges of an octagon with edge length b +7170 REM in the colour endcoded by colorNo +7180 CALL polygonPart(b, 8, true, 4, colorNo) +7190 CALL forward(b + 2*c, colorNo) +7200 REM Counterclockwise draw 4 edges of an octagon with edge length b +7210 REM in the colour endcoded by colorNo +7220 CALL polygonPart(b, 8, true, 4, colorNo) +7230 CALL forward(b + 2*c, colorNo) +7240 penUp() +7250 forward(c) : REM color = ffffff +7260 left(90) +7270 forward(b + 2*c) : REM color = ffffff +7280 penDown() +7290 left(90) +7300 END SUB +7310 REM +7320 REM Draws letter P in colour specified by colorNo with font height h +7330 REM from the current turtle position. +7340 REM TODO: Add type-specific suffixes where necessary! +7350 SUB letterP(h, colorNo) +7360 REM TODO: add the respective type suffixes to your variable names if required +7370 REM Octagon edge length +7380 LET b = h * 0.5 / (sqrt(2.0) + 1) +7390 REM Cathetus of the corner triangle outside the octagon +7400 LET c = b / sqrt(2.0) +7410 CALL forward(h, colorNo) +7420 right(90) +7430 CALL forward(c+b, colorNo) +7440 REM Clockwise draw 4 edges of an octagon with edge length b +7450 REM in the colour endcoded by colorNo +7460 CALL polygonPart(b, 8, false, 4, colorNo) +7470 CALL forward(c, colorNo) +7480 penUp() +7490 backward(b + 2*c) : REM color = ffffff +7500 left(90) +7510 forward(b + 2*c) : REM color = ffffff +7520 penDown() +7530 left(180) +7540 END SUB +7550 REM +7560 REM Draws letter Q in colour specified by colorNo with font height h +7570 REM from the current turtle position. +7580 REM TODO: Add type-specific suffixes where necessary! +7590 SUB letterQ(h, colorNo) +7600 REM TODO: add the respective type suffixes to your variable names if required +7610 REM Achteck-Kantenlänge +7620 LET b = h * 0.5 / (sqrt(2.0) + 1) +7630 REM Eckenlänge außen am Achteck +7640 LET c = b / sqrt(2.0) +7650 REM 360°/8 +7660 LET rotAngle = 45 +7670 penUp() +7680 forward(c) : REM color = ffffff +7690 penDown() +7700 right(180) +7710 REM Counterclockwise draw 4 edges of an octagon with edge length b +7720 REM in the colour endcoded by colorNo +7730 CALL polygonPart(b, 8, true, 4, colorNo) +7740 CALL forward(b + 2*c, colorNo) +7750 REM Counterclockwise draw 4 edges of an octagon with edge length b +7760 REM in the colour endcoded by colorNo +7770 CALL polygonPart(b, 8, true, 4, colorNo) +7780 CALL forward(b + 2*c, colorNo) +7790 penUp() +7800 forward(c) : REM color = ffffff +7810 left(90) +7820 forward(b + 2*c) : REM color = ffffff +7830 right(rotAngle) +7840 backward(b) : REM color = ffffff +7850 penDown() +7860 CALL forward(b, colorNo) +7870 left(90 + rotAngle) +7880 END SUB +7890 REM +7900 REM Zeichnet den Buchstaben R von der Turtleposition aus +7910 REM mit Zeilenhöhe h +7920 REM TODO: Add type-specific suffixes where necessary! +7930 SUB letterR(h, colorNo) +7940 REM TODO: add the respective type suffixes to your variable names if required +7950 REM Achteck-Kantenlänge +7960 LET b = h * 0.5 / (sqrt(2.0) + 1) +7970 REM Eckenlänge außen am Achteck +7980 LET c = b / sqrt(2.0) +7990 REM 360°/8 +8000 LET rotAngle = 45 +8010 CALL forward(h, colorNo) +8020 right(90) +8030 CALL forward(c+b, colorNo) +8040 REM Clockwise draw 4 edges of an octagon with edge length b +8050 REM in the colour endcoded by colorNo +8060 CALL polygonPart(b, 8, false, 4, colorNo) +8070 CALL forward(c, colorNo) +8080 left(90 + rotAngle) +8090 CALL forward(sqrt(2.0)*(b + 2*c), colorNo) +8100 left(90 + rotAngle) +8110 END SUB +8120 REM +8130 REM Draws letter S in colour specified by colorNo with font height h +8140 REM from the current turtle position. +8150 REM TODO: Add type-specific suffixes where necessary! +8160 SUB letterS(h, colorNo) +8170 REM TODO: add the respective type suffixes to your variable names if required +8180 REM Achteck-Kantenlänge +8190 LET b = h * 0.5 / (sqrt(2.0) + 1) +8200 REM Eckenlänge außen am Achteck +8210 LET c = b / sqrt(2.0) +8220 REM 360°/8 +8230 LET rotAngle = 45 +8240 penUp() +8250 forward(c) : REM color = ffffff +8260 penDown() +8270 right(180) +8280 REM Counterclockwise draw 6 edges of an octagon with edge length b +8290 REM in the colour endcoded by colorNo +8300 CALL polygonPart(b, 8, true, 6, colorNo) +8310 REM Clockwise draw 5 edges of an octagon with edge length b +8320 REM in the colour endcoded by colorNo +8330 CALL polygonPart(b, 8, false, 5, colorNo) +8340 right(rotAngle) +8350 penUp() +8360 forward(2*b + 3*c) : REM color = ffffff +8370 penDown() +8380 left(180) +8390 END SUB +8400 REM +8410 REM Draws letter U in colour specified by colorNo with font height h +8420 REM from the current turtle position. +8430 REM TODO: Add type-specific suffixes where necessary! +8440 SUB letterU(h, colorNo) +8450 REM TODO: add the respective type suffixes to your variable names if required +8460 REM edge length of a regular octagon +8470 LET b = h * 0.5 / (sqrt(2.0) + 1) +8480 REM Eckenlänge außen am Achteck +8490 LET c = b / sqrt(2.0) +8500 REM 360°/8 +8510 LET rotAngle = 45 +8520 penUp() +8530 forward(c) : REM color = ffffff +8540 penDown() +8550 CALL forward(h - c, colorNo) +8560 penUp() +8570 backward(h-c) : REM color = ffffff +8580 penDown() +8590 right(180) +8600 REM Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo +8610 CALL polygonPart(b, 8, true, 3, colorNo) +8620 left(rotAngle) +8630 CALL forward(h - c, colorNo) +8640 penUp() +8650 backward(h) : REM color = ffffff +8660 penDown() +8670 END SUB +8680 REM +8690 REM Draws a question mark in colour specified by colorNo with font height h +8700 REM from the current turtle position. +8710 REM TODO: Add type-specific suffixes where necessary! +8720 SUB qstnMk(h, colorNo) +8730 REM TODO: add the respective type suffixes to your variable names if required +8740 REM Achteck-Kantenlänge +8750 LET b = h * 0.5 / (sqrt(2.0) + 1) +8760 REM Eckenlänge außen am Achteck +8770 LET c = b / sqrt(2.0) +8780 REM 360°/8 +8790 LET rotAngle = 45 +8800 penUp() +8810 forward(h-c) : REM color = ffffff +8820 penDown() +8830 REM Counterclockwise draw 5 edges of an octagon with edge length b +8840 REM in the colour endcoded by colorNo +8850 CALL polygonPart(b, 8, false, 5, colorNo) +8860 CALL forward(c, colorNo) +8870 left(rotAngle) +8880 CALL forward(b/2.0, colorNo) +8890 penUp() +8900 forward(c) : REM color = ffffff +8910 left(90) +8920 forward(c/2.0) : REM color = ffffff +8930 penDown() +8940 REM Counterclockwise draw all 4 edges of a squarfe with edge length c +8950 REM in the colour endcoded by colorNo +8960 CALL polygonPart(c, 4, false, 4, colorNo) +8970 penUp() +8980 forward((c + b)/2.0) : REM color = ffffff +8990 left(90) +9000 backward(c) : REM color = ffffff +9010 penDown() +9020 END SUB +9030 REM +9040 REM Has the turtle draw the given string 'text´ with font height 'h´ (in +9050 REM pixels) and the colour coded by integer 'c´ from the current Turtle +9060 REM position to the Turtle canvas. If the turtle looks North then +9070 REM the text will be written rightwards. In the event, the turtle will be +9080 REM placed behind the text in original orientation (such that the next text +9090 REM would be written like a continuation. Colour codes: +9100 REM 1 = black +9110 REM 2 = red +9120 REM 3 = yellow +9130 REM 4 = green +9140 REM 5 = cyan +9150 REM 6 = blue +9160 REM 7 = pink +9170 REM 8 = grey +9180 REM 9 = orange +9190 REM 10 = violet +9200 REM All letters (ASCII) will be converted to uppercase, digits cannot +9210 REM be represented, the set of representable special characters is: +9220 REM '.', ',', '!', '?'. Other characters will be shown as a small +9230 REM centred square (dummy character). +9240 REM TODO: Add type-specific suffixes where necessary! +9250 SUB drawText(text AS String, h AS integer, c AS integer) +9260 REM TODO: add the respective type suffixes to your variable names if required +9270 LET gap = h/10.0 +9280 FOR k = 1 TO length(text) +9290 LET letter = uppercase(copy(text, k, 1)) +9300 IF letter = "," THEN +9310 CALL comma(h,c) +9320 ELSE +9330 REM "," cannot be chacked against because the comma is misinterpreted +9340 REM as selector list separator. +9350 SELECT CASE letter +9360 CASE "A" +9370 CALL letterA(h,c) +9380 CASE "B" +9390 CALL letterB(h,c) +9400 CASE "C" +9410 CALL letterC(h,c) +9420 CASE "D" +9430 CALL letterD(h,c) +9440 CASE "E" +9450 CALL letterE(h,c) +9460 CASE "F" +9470 CALL letterF(h,c) +9480 CASE "G" +9490 CALL letterG(h,c) +9500 CASE "H" +9510 CALL letterH(h,c) +9520 CASE "I" +9530 CALL letterI(h,c) +9540 CASE "J" +9550 CALL letterJ(h,c) +9560 CASE "K" +9570 CALL letterK(h,c) +9580 CASE "L" +9590 CALL letterL(h,c) +9600 CASE "M" +9610 CALL letterM(h,c) +9620 CASE "N" +9630 CALL letterN(h,c) +9640 CASE "O" +9650 CALL letterO(h,c) +9660 CASE "P" +9670 CALL letterP(h,c) +9680 CASE "Q" +9690 CALL letterQ(h,c) +9700 CASE "R" +9710 CALL letterR(h,c) +9720 CASE "S" +9730 CALL letterS(h,c) +9740 CASE "T" +9750 CALL letterT(h,c) +9760 CASE "U" +9770 CALL letterU(h,c) +9780 CASE "V" +9790 CALL letterV(h,c) +9800 CASE "W" +9810 CALL letterW(h,c) +9820 CASE "X" +9830 CALL letterX(h,c) +9840 CASE "Y" +9850 CALL letterY(h,c) +9860 CASE "Z" +9870 CALL letterZ(h,c) +9880 CASE " " +9890 CALL blank(h,c) +9900 CASE "!" +9910 CALL exclMk(h,c) +9920 CASE "?" +9930 CALL qstnMk(h,c) +9940 CASE "." +9950 CALL fullSt(h,c) +9960 CASE ELSE +9970 CALL charDummy(h,c) +9980 END SELECT +9990 END IF +10000 right(90) +10010 penUp() +10020 forward(gap) : REM color = ffffff +10030 penDown() +10040 left(90) +10050 NEXT k +10060 END SUB diff --git a/samples/export/BASIC1/ELIZA_2.3.bas b/samples/export/BASIC1/ELIZA_2.3.bas new file mode 100644 index 00000000..d480526a --- /dev/null +++ b/samples/export/BASIC1/ELIZA_2.3.bas @@ -0,0 +1,428 @@ +Rem Concept and lisp implementation published by Joseph Weizenbaum (MIT): +Rem "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +Rem Computational Linguistis 1(1966)9, pp. 36-45 +Rem Revision history: +Rem 2016-10-06 Initial version +Rem 2017-03-29 Two diagrams updated (comments translated to English) +Rem 2017-03-29 More keywords and replies added +Rem 2019-03-14 Replies and mapping reorganised for easier maintenance +Rem 2019-03-15 key map joined from keyword array and index map +Rem 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +Rem 2019-11-28 New global type "History" (to ensure a homogenous array) +Rem Generated by Structorizer 3.30-03 +Rem +Rem Copyright (C) 2018-05-14 Kay Gürtzig +Rem License: GPLv3-link +Rem GNU General Public License (V 3) +Rem https://www.gnu.org/licenses/gpl.html +Rem http://www.gnu.de/documents/gpl.de.html +Rem +Rem +Rem program ELIZA +Rem TODO: Check and accomplish your variable declarations here: +Dim varPart As String +Dim userInput As String +Dim replyRing As ??? +Dim reply As String +Dim replies()() As String +Dim reflexions()() As String +Dim posAster As Integer +Dim offsets() As Integer +Dim keyMap() As KeyMapEntry +Dim keyIndex As ??? +Dim isRepeated As boolean +Dim isGone As boolean +Dim history As History +Dim findInfo() As integer +Dim entry As KeyMapEntry +Dim byePhrases()() As String +Rem +Rem Title information +PRINT "************* ELIZA **************" +PRINT "* Original design by J. Weizenbaum" +PRINT "**********************************" +PRINT "* Adapted for Basic on IBM PC by" +PRINT "* - Patricia Danielson" +PRINT "* - Paul Hashfield" +PRINT "**********************************" +PRINT "* Adapted for Structorizer by" +PRINT "* - Kay Gürtzig / FH Erfurt 2016" +PRINT "* Version: 2.3 (2019-11-28)" +PRINT "* (Requires at least Structorizer 3.30-03 to run)" +PRINT "**********************************" +Rem Stores the last five inputs of the user in a ring buffer, +Rem the second component is the rolling (over-)write index. +Let history.histArray = Array("", "", "", "", "") +Let history.histIndex = 0 +const replies = setupReplies() +const reflexions = setupReflexions() +const byePhrases = setupGoodByePhrases() +const keyMap = setupKeywords() +offsets(length(keyMap)-1) = 0 +isGone = false +Rem Starter +PRINT "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?" +Do + INPUT userInput + Rem Converts the input to lowercase, cuts out interpunctation + Rem and pads the string + userInput = normalizeInput(userInput) + isGone = checkGoodBye(userInput, byePhrases) + If NOT isGone Then + reply = "Please don\'t repeat yourself!" + isRepeated = checkRepetition(history, userInput) + If NOT isRepeated Then + findInfo = findKeyword(keyMap, userInput) + keyIndex = findInfo(0) + If keyIndex < 0 Then + Rem Should never happen... + keyIndex = length(keyMap)-1 + End If + var entry: KeyMapEntry = keyMap(keyIndex) + Rem Variable part of the reply + varPart = "" + If length(entry.keyword) > 0 Then + varPart = conjugateStrings(userInput, entry.keyword, findInfo(1), reflexions) + End If + replyRing = replies(entry.index) + reply = replyRing(offsets(keyIndex)) + offsets(keyIndex) = (offsets(keyIndex) + 1) % length(replyRing) + posAster = pos("*", reply) + If posAster > 0 Then + If varPart = " " Then + reply = "You will have to elaborate more for me to help you." + Else + delete(reply, posAster, 1) + insert(varPart, reply, posAster) + End If + End If + reply = adjustSpelling(reply) + End If + PRINT reply + End If +Loop Until isGone +End +Rem +Rem Cares for correct letter case among others +Rem TODO: Check (and specify if needed) the argument and result types! +Function adjustSpelling(sentence AS String) As String + Rem TODO: Check and accomplish your variable declarations here: + Dim word As String + Dim start As String + Dim result As String + Dim position As Integer + Rem + result = sentence + position = 1 + Do While (position <= length(sentence)) AND (copy(sentence, position, 1) = " ") + position = position + 1 + Loop + If position <= length(sentence) Then + start = copy(sentence, 1, position) + delete(result, 1, position) + insert(uppercase(start), result, 1) + End If + Dim array53d059() As String = {" i ", " i\'"} + For Each word In array53d059 + position = pos(word, result) + Do While position > 0 + delete(result, position+1, 1) + insert("I", result, position+1) + position = pos(word, result) + Loop + Next word + Return result +End Function +Rem +Rem Checks whether the given text contains some kind of +Rem good-bye phrase inducing the end of the conversation +Rem and if so writes a correspding good-bye message and +Rem returns true, otherwise false +Rem TODO: Check (and specify if needed) the argument and result types! +Function checkGoodBye(text AS String, phrases AS array of array[0..1] of string) As boolean + Rem TODO: Check and accomplish your variable declarations here: + Dim saidBye As boolean + Dim pair() As String + Rem + For Each pair In phrases + If pos(pair(0), text) > 0 Then + saidBye = true + PRINT pair(1) + Return true + End If + Next pair + return false +End Function +Rem +Rem Checks whether newInput has occurred among the recently cached +Rem input strings in the histArray component of history and updates the history. +Rem TODO: Check (and specify if needed) the argument and result types! +Function checkRepetition(history AS History, newInput AS String) As boolean + Rem TODO: Check and accomplish your variable declarations here: + Dim i As Integer + Dim histDepth As Integer + Dim hasOccurred As boolean + Rem + hasOccurred = false + If length(newInput) > 4 Then + histDepth = length(history.histArray) + For i = 0 To histDepth-1 + If newInput = history.histArray(i) Then + hasOccurred = true + End If + Next i + history.histArray(history.histIndex) = newInput + history.histIndex = (history.histIndex + 1) % (histDepth) + End If + return hasOccurred +End Function +Rem +Rem TODO: Check (and specify if needed) the argument and result types! +Function conjugateStrings(sentence AS String, key AS String, keyPos AS integer, flexions AS array of array[0..1] of string) As String + Rem TODO: Check and accomplish your variable declarations here: + Dim right As String + Dim result As String + Dim position As Integer + Dim pair() As String + Dim left As String + Rem + result = " " + copy(sentence, keyPos + length(key), length(sentence)) + " " + For Each pair In flexions + left = "" + right = result + position = pos(pair(0), right) + Do While position > 0 + left = left + copy(right, 1, position-1) + pair(1) + right = copy(right, position + length(pair(0)), length(right)) + position = pos(pair(0), right) + Loop + result = left + right + Next pair + Rem Eliminate multiple spaces + position = pos(" ", result) + Do While position > 0 + result = copy(result, 1, position-1) + copy(result, position+1, length(result)) + position = pos(" ", result) + Loop + Return result +End Function +Rem +Rem Looks for the occurrence of the first of the strings +Rem contained in keywords within the given sentence (in +Rem array order). +Rem Returns an array of +Rem 0: the index of the first identified keyword (if any, otherwise -1), +Rem 1: the position inside sentence (0 if not found) +Rem TODO: Check (and specify if needed) the argument and result types! +Function findKeyword(keyMap AS const array of KeyMapEntry, sentence AS String) As array[0..1] of integer + Rem TODO: Check and accomplish your variable declarations here: + Dim result() As Integer + Dim position As Integer + Dim i As Integer + Dim entry As KeyMapEntry + Rem + Rem Contains the index of the keyword and its position in sentence + Let result = Array(-1, 0) + i = 0 + Do While (result(0) < 0) AND (i < length(keyMap)) + var entry: KeyMapEntry = keyMap(i) + position = pos(entry.keyword, sentence) + If position > 0 Then + result(0) = i + result(1) = position + End If + i = i+1 + Loop + Return result +End Function +Rem +Rem Converts the sentence to lowercase, eliminates all +Rem interpunction (i.e. ',', '.', ';'), and pads the +Rem sentence among blanks +Rem TODO: Check (and specify if needed) the argument and result types! +Function normalizeInput(sentence AS String) As String + Rem TODO: Check and accomplish your variable declarations here: + Dim symbol As String + Dim result As String + Dim position As Integer + Rem + sentence = lowercase(sentence) + Rem TODO: Specify an appropriate element type for the array! + Dim array450125a4() As FIXME_450125a4 = {'.', ',', ';', '!', '?'} + For Each symbol In array450125a4 + position = pos(symbol, sentence) + Do While position > 0 + sentence = copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)) + position = pos(symbol, sentence) + Loop + Next symbol + result = " " + sentence + " " + Return result +End Function +Rem +Rem TODO: Check (and specify if needed) the argument and result types! +Function setupGoodByePhrases() As array of array[0..1] of string + Rem TODO: Check and accomplish your variable declarations here: + Dim phrases()() As String + Rem + Let phrases(0) = Array(" shut", "Okay. If you feel that way I\'ll shut up. ... Your choice.") + Let phrases(1) = Array("bye", "Well, let\'s end our talk for now. See you later. Bye.") + return phrases +End Function +Rem +Rem The lower the index the higher the rank of the keyword (search is sequential). +Rem The index of the first keyword found in a user sentence maps to a respective +Rem reply ring as defined in `setupReplies()´. +Rem TODO: Check (and specify if needed) the argument and result types! +Function setupKeywords() As array of KeyMapEntry + Rem TODO: Check and accomplish your variable declarations here: + Dim keywords() As KeyMapEntry + Rem + Rem The empty key string (last entry) is the default clause - will always be found + Let keywords(39).keyword = "" + Let keywords(39).index = 29 + Let keywords(0).keyword = "can you " + Let keywords(0).index = 0 + Let keywords(1).keyword = "can i " + Let keywords(1).index = 1 + Let keywords(2).keyword = "you are " + Let keywords(2).index = 2 + Let keywords(3).keyword = "you\'re " + Let keywords(3).index = 2 + Let keywords(4).keyword = "i don't " + Let keywords(4).index = 3 + Let keywords(5).keyword = "i feel " + Let keywords(5).index = 4 + Let keywords(6).keyword = "why don\'t you " + Let keywords(6).index = 5 + Let keywords(7).keyword = "why can\'t i " + Let keywords(7).index = 6 + Let keywords(8).keyword = "are you " + Let keywords(8).index = 7 + Let keywords(9).keyword = "i can\'t " + Let keywords(9).index = 8 + Let keywords(10).keyword = "i am " + Let keywords(10).index = 9 + Let keywords(11).keyword = "i\'m " + Let keywords(11).index = 9 + Let keywords(12).keyword = "you " + Let keywords(12).index = 10 + Let keywords(13).keyword = "i want " + Let keywords(13).index = 11 + Let keywords(14).keyword = "what " + Let keywords(14).index = 12 + Let keywords(15).keyword = "how " + Let keywords(15).index = 12 + Let keywords(16).keyword = "who " + Let keywords(16).index = 12 + Let keywords(17).keyword = "where " + Let keywords(17).index = 12 + Let keywords(18).keyword = "when " + Let keywords(18).index = 12 + Let keywords(19).keyword = "why " + Let keywords(19).index = 12 + Let keywords(20).keyword = "name " + Let keywords(20).index = 13 + Let keywords(21).keyword = "cause " + Let keywords(21).index = 14 + Let keywords(22).keyword = "sorry " + Let keywords(22).index = 15 + Let keywords(23).keyword = "dream " + Let keywords(23).index = 16 + Let keywords(24).keyword = "hello " + Let keywords(24).index = 17 + Let keywords(25).keyword = "hi " + Let keywords(25).index = 17 + Let keywords(26).keyword = "maybe " + Let keywords(26).index = 18 + Let keywords(27).keyword = " no" + Let keywords(27).index = 19 + Let keywords(28).keyword = "your " + Let keywords(28).index = 20 + Let keywords(29).keyword = "always " + Let keywords(29).index = 21 + Let keywords(30).keyword = "think " + Let keywords(30).index = 22 + Let keywords(31).keyword = "alike " + Let keywords(31).index = 23 + Let keywords(32).keyword = "yes " + Let keywords(32).index = 24 + Let keywords(33).keyword = "friend " + Let keywords(33).index = 25 + Let keywords(34).keyword = "computer" + Let keywords(34).index = 26 + Let keywords(35).keyword = "bot " + Let keywords(35).index = 26 + Let keywords(36).keyword = "smartphone" + Let keywords(36).index = 27 + Let keywords(37).keyword = "father " + Let keywords(37).index = 28 + Let keywords(38).keyword = "mother " + Let keywords(38).index = 28 + return keywords +End Function +Rem +Rem Returns an array of pairs of mutualy substitutable +Rem TODO: Check (and specify if needed) the argument and result types! +Function setupReflexions() As array of array[0..1] of string + Rem TODO: Check and accomplish your variable declarations here: + Dim reflexions()() As String + Rem + Let reflexions(0) = Array(" are ", " am ") + Let reflexions(1) = Array(" were ", " was ") + Let reflexions(2) = Array(" you ", " I ") + Let reflexions(3) = Array(" your", " my") + Let reflexions(4) = Array(" i\'ve ", " you\'ve ") + Let reflexions(5) = Array(" i\'m ", " you\'re ") + Let reflexions(6) = Array(" me ", " you ") + Let reflexions(7) = Array(" my ", " your ") + Let reflexions(8) = Array(" i ", " you ") + Let reflexions(9) = Array(" am ", " are ") + return reflexions +End Function +Rem +Rem This routine sets up the reply rings addressed by the key words defined in +Rem routine `setupKeywords()´ and mapped hitherto by the cross table defined +Rem in `setupMapping()´ +Rem TODO: Check (and specify if needed) the argument and result types! +Function setupReplies() As array of array of string + Rem TODO: Check and accomplish your variable declarations here: + Dim setupReplies()() As String + Dim replies()() As String + Rem + var replies: array of array of String + Rem We start with the highest index for performance reasons + Rem (is to avoid frequent array resizing) + Let replies(29) = Array( "Say, do you have any psychological problems?", "What does that suggest to you?", "I see.", "I'm not sure I understand you fully.", "Come come elucidate your thoughts.", "Can you elaborate on that?", "That is quite interesting.") + Let replies(0) = Array( "Don't you believe that I can*?", "Perhaps you would like to be like me?", "You want me to be able to*?") + Let replies(1) = Array( "Perhaps you don't want to*?", "Do you want to be able to*?") + Let replies(2) = Array( "What makes you think I am*?", "Does it please you to believe I am*?", "Perhaps you would like to be*?", "Do you sometimes wish you were*?") + Let replies(3) = Array( "Don't you really*?", "Why don't you*?", "Do you wish to be able to*?", "Does that trouble you*?") + Let replies(4) = Array( "Do you often feel*?", "Are you afraid of feeling*?", "Do you enjoy feeling*?") + Let replies(5) = Array( "Do you really believe I don't*?", "Perhaps in good time I will*.", "Do you want me to*?") + Let replies(6) = Array( "Do you think you should be able to*?", "Why can't you*?") + Let replies(7) = Array( "Why are you interested in whether or not I am*?", "Would you prefer if I were not*?", "Perhaps in your fantasies I am*?") + Let replies(8) = Array( "How do you know you can't*?", "Have you tried?","Perhaps you can now*.") + Let replies(9) = Array( "Did you come to me because you are*?", "How long have you been*?", "Do you believe it is normal to be*?", "Do you enjoy being*?") + Let replies(10) = Array( "We were discussing you--not me.", "Oh, I*.", "You're not really talking about me, are you?") + Let replies(11) = Array( "What would it mean to you if you got*?", "Why do you want*?", "Suppose you soon got*...", "What if you never got*?", "I sometimes also want*.") + Let replies(12) = Array( "Why do you ask?", "Does that question interest you?", "What answer would please you the most?", "What do you think?", "Are such questions on your mind often?", "What is it that you really want to know?", "Have you asked anyone else?", "Have you asked such questions before?", "What else comes to mind when you ask that?") + Let replies(13) = Array( "Names don't interest me.", "I don't care about names -- please go on.") + Let replies(14) = Array( "Is that the real reason?", "Don't any other reasons come to mind?", "Does that reason explain anything else?", "What other reasons might there be?") + Let replies(15) = Array( "Please don't apologize!", "Apologies are not necessary.", "What feelings do you have when you apologize?", "Don't be so defensive!") + Let replies(16) = Array( "What does that dream suggest to you?", "Do you dream often?", "What persons appear in your dreams?", "Are you disturbed by your dreams?") + Let replies(17) = Array( "How do you do ...please state your problem.") + Let replies(18) = Array( "You don't seem quite certain.", "Why the uncertain tone?", "Can't you be more positive?", "You aren't sure?", "Don't you know?") + Let replies(19) = Array( "Are you saying no just to be negative?", "You are being a bit negative.", "Why not?", "Are you sure?", "Why no?") + Let replies(20) = Array( "Why are you concerned about my*?", "What about your own*?") + Let replies(21) = Array( "Can you think of a specific example?", "When?", "What are you thinking of?", "Really, always?") + Let replies(22) = Array( "Do you really think so?", "But you are not sure you*?", "Do you doubt you*?") + Let replies(23) = Array( "In what way?", "What resemblance do you see?", "What does the similarity suggest to you?", "What other connections do you see?", "Could there really be some connection?", "How?", "You seem quite positive.") + Let replies(24) = Array( "Are you sure?", "I see.", "I understand.") + Let replies(25) = Array( "Why do you bring up the topic of friends?", "Do your friends worry you?", "Do your friends pick on you?", "Are you sure you have any friends?", "Do you impose on your friends?", "Perhaps your love for friends worries you.") + Let replies(26) = Array( "Do computers worry you?", "Are you talking about me in particular?", "Are you frightened by machines?", "Why do you mention computers?", "What do you think machines have to do with your problem?", "Don't you think computers can help people?", "What is it about machines that worries you?") + Let replies(27) = Array( "Do you sometimes feel uneasy without a smartphone?", "Have you had these phantasies before?", "Does the world seem more real for you via apps?") + Let replies(28) = Array( "Tell me more about your family.", "Who else in your family*?", "What does family relations mean for you?", "Come on, How old are you?") + setupReplies = replies + Return setupReplies +End Function diff --git a/samples/export/BASIC1/SORTING_TEST_MAIN.bas b/samples/export/BASIC1/SORTING_TEST_MAIN.bas index 16446657..bd3d1b78 100644 --- a/samples/export/BASIC1/SORTING_TEST_MAIN.bas +++ b/samples/export/BASIC1/SORTING_TEST_MAIN.bas @@ -1,294 +1,294 @@ -REM Creates three equal arrays of numbers and has them sorted with different sorting algorithms -REM to allow performance comparison via execution counting ("Collect Runtime Data" should -REM sensibly be switched on). -REM Requested input data are: Number of elements (size) and filing mode. -REM Generated by Structorizer 3.30-02 -REM -REM Copyright (C) 2019-10-02 Kay Gürtzig -REM License: GPLv3-link -REM GNU General Public License (V 3) -REM https://www.gnu.org/licenses/gpl.html -REM http://www.gnu.de/documents/gpl.de.html -REM -REM -REM program SORTING_TEST_MAIN -REM TODO: declare your variables here: - REM DIM values3 AS - REM DIM values2 AS - REM DIM values1 AS - REM DIM show AS - REM DIM ok3 AS - REM DIM ok2 AS - REM DIM ok1 AS - REM DIM modus AS - REM DIM i AS - REM DIM elementCount AS -REM -DO +Rem Creates three equal arrays of numbers and has them sorted with different sorting algorithms +Rem to allow performance comparison via execution counting ("Collect Runtime Data" should +Rem sensibly be switched on). +Rem Requested input data are: Number of elements (size) and filing mode. +Rem Generated by Structorizer 3.30-03 +Rem +Rem Copyright (C) 2019-10-02 Kay Gürtzig +Rem License: GPLv3-link +Rem GNU General Public License (V 3) +Rem https://www.gnu.org/licenses/gpl.html +Rem http://www.gnu.de/documents/gpl.de.html +Rem +Rem +Rem program SORTING_TEST_MAIN +Rem TODO: Check and accomplish your variable declarations here: +Dim values3() As ??? +Dim values2() As ??? +Dim values1() As Integer +Dim show As ??? +Dim ok3 As bool +Dim ok2 As bool +Dim ok1 As bool +Dim modus As ??? +Dim i As Integer +Dim elementCount As ??? +Rem +Do INPUT elementCount -LOOP UNTIL elementCount >= 1 -DO +Loop Until elementCount >= 1 +Do PRINT "Filling: 1 = random, 2 = increasing, 3 = decreasing"; : INPUT modus -LOOP UNTIL modus = 1 OR modus = 2 OR modus = 3 -FOR i = 0 TO elementCount-1 - SELECT CASE modus - CASE 1 +Loop Until modus = 1 OR modus = 2 OR modus = 3 +For i = 0 To elementCount-1 + Select Case modus + Case 1 values1(i) = random(10000) - CASE 2 + Case 2 values1(i) = i - CASE 3 + Case 3 values1(i) = -i - END SELECT -NEXT i -REM Kopiere das Array für exakte Vergleichbarkeit -FOR i = 0 TO elementCount-1 + End Select +Next i +Rem Copy the array for exact comparability +For i = 0 To elementCount-1 values2(i) = values1(i) values3(i) = values1(i) -NEXT i +Next i -REM ========================================================== -REM ================= START PARALLEL SECTION ================= -REM ========================================================== -REM TODO: add the necessary code to run the threads concurrently +Rem ========================================================== +Rem ================= START PARALLEL SECTION ================= +Rem ========================================================== +Rem TODO: add the necessary code to run the threads concurrently - REM ----------------- START THREAD 0 ----------------- - CALL bubbleSort(values1) - REM ------------------ END THREAD 0 ------------------ + Rem ----------------- START THREAD 0 ----------------- + Call bubbleSort(values1) + Rem ------------------ END THREAD 0 ------------------ - REM ----------------- START THREAD 1 ----------------- - CALL quickSort(values2, 0, elementCount) - REM ------------------ END THREAD 1 ------------------ + Rem ----------------- START THREAD 1 ----------------- + Call quickSort(values2, 0, elementCount) + Rem ------------------ END THREAD 1 ------------------ - REM ----------------- START THREAD 2 ----------------- - CALL heapSort(values3) - REM ------------------ END THREAD 2 ------------------ + Rem ----------------- START THREAD 2 ----------------- + Call heapSort(values3) + Rem ------------------ END THREAD 2 ------------------ -REM ========================================================== -REM ================== END PARALLEL SECTION ================== -REM ========================================================== +Rem ========================================================== +Rem ================== END PARALLEL SECTION ================== +Rem ========================================================== -CALL ok1 = testSorted(values1) -CALL ok2 = testSorted(values2) -CALL ok3 = testSorted(values3) -IF NOT ok1 OR NOT ok2 OR NOT ok3 THEN - FOR i = 0 TO elementCount-1 - IF values1(i) <> values2(i) OR values1(i) <> values3(i) THEN +ok1 = testSorted(values1) +ok2 = testSorted(values2) +ok3 = testSorted(values3) +If NOT ok1 OR NOT ok2 OR NOT ok3 Then + For i = 0 To elementCount-1 + If values1(i) <> values2(i) OR values1(i) <> values3(i) Then PRINT "Difference at ["; i; "]: "; values1(i); " <-> "; values2(i); " <-> "; values3(i) - END IF - NEXT i -END IF -DO + End If + Next i +End If +Do PRINT "Show arrays (yes/no)?"; : INPUT show -LOOP UNTIL show = "yes" OR show = "no" -IF show = "yes" THEN - FOR i = 0 TO elementCount - 1 +Loop Until show = "yes" OR show = "no" +If show = "yes" Then + For i = 0 To elementCount - 1 PRINT "["; i; "]:\t"; values1(i); "\t"; values2(i); "\t"; values3(i) - NEXT i -END IF -END -REM -REM Implements the well-known BubbleSort algorithm. -REM Compares neigbouring elements and swaps them in case of an inversion. -REM Repeats this while inversions have been found. After every -REM loop passage at least one element (the largest one out of the -REM processed subrange) finds its final place at the end of the -REM subrange. -REM TODO: Check (and specify if needed) the argument and result types! -SUB bubbleSort(values) - REM TODO: declare your variables here: - REM DIM temp AS - REM DIM posSwapped AS - REM DIM i AS - REM DIM ende AS - REM + Next i +End If +End +Rem +Rem Implements the well-known BubbleSort algorithm. +Rem Compares neigbouring elements and swaps them in case of an inversion. +Rem Repeats this while inversions have been found. After every +Rem loop passage at least one element (the largest one out of the +Rem processed subrange) finds its final place at the end of the +Rem subrange. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub bubbleSort(values) + Rem TODO: Check and accomplish your variable declarations here: + Dim temp As ??? + Dim posSwapped As ??? + Dim i As Integer + Dim ende As ??? + Rem ende = length(values) - 2 - DO - REM The index of the most recent swapping (-1 means no swapping done). + Do + Rem The index of the most recent swapping (-1 means no swapping done). posSwapped = -1 - FOR i = 0 TO ende - IF values(i) > values(i+1) THEN + For i = 0 To ende + If values(i) > values(i+1) Then temp = values(i) values(i) = values(i+1) values(i+1) = temp posSwapped = i - END IF - NEXT i + End If + Next i ende = posSwapped - 1 - LOOP UNTIL posSwapped < 0 -END SUB -REM -REM Given a max-heap 'heap´ with element at index 'i´ possibly -REM violating the heap property wrt. its subtree upto and including -REM index range-1, restores heap property in the subtree at index i -REM again. -REM TODO: Check (and specify if needed) the argument and result types! -SUB maxHeapify(heap, i, range) - REM TODO: declare your variables here: - REM DIM temp AS - REM DIM right AS - REM DIM max AS - REM DIM left AS - REM - REM Indices of left and right child of node i + Loop Until posSwapped < 0 +End Sub +Rem +Rem Given a max-heap 'heap´ with element at index 'i´ possibly +Rem violating the heap property wrt. its subtree upto and including +Rem index range-1, restores heap property in the subtree at index i +Rem again. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub maxHeapify(heap, i, range) + Rem TODO: Check and accomplish your variable declarations here: + Dim temp As ??? + Dim right As ??? + Dim max As ??? + Dim left As ??? + Rem + Rem Indices of left and right child of node i right = (i+1) * 2 left = right - 1 - REM Index of the (local) maximum + Rem Index of the (local) maximum max = i - IF left < range AND heap(left) > heap(i) THEN + If left < range AND heap(left) > heap(i) Then max = left - END IF - IF right < range AND heap(right) > heap(max) THEN + End If + If right < range AND heap(right) > heap(max) Then max = right - END IF - IF max <> i THEN + End If + If max <> i Then temp = heap(i) heap(i) = heap(max) heap(max) = temp - CALL maxHeapify(heap, max, range) - END IF -END SUB -REM -REM Partitions array values between indices start und stop-1 with -REM respect to the pivot element initially at index p into smaller -REM and greater elements. -REM Returns the new (and final) index of the pivot element (which -REM separates the sequence of smaller from the sequence of greater -REM elements). -REM This is not the most efficient algorithm (about half the swapping -REM might still be avoided) but it is pretty clear. -REM TODO: Check (and specify if needed) the argument and result types! -FUNCTION partition(values, start, stop, p) AS Integer - REM TODO: declare your variables here: - REM DIM seen AS - REM DIM pivot AS - REM + Call maxHeapify(heap, max, range) + End If +End Sub +Rem +Rem Partitions array values between indices start und stop-1 with +Rem respect to the pivot element initially at index p into smaller +Rem and greater elements. +Rem Returns the new (and final) index of the pivot element (which +Rem separates the sequence of smaller from the sequence of greater +Rem elements). +Rem This is not the most efficient algorithm (about half the swapping +Rem might still be avoided) but it is pretty clear. +Rem TODO: Check (and specify if needed) the argument and result types! +Function partition(values, start, stop, p) As Integer + Rem TODO: Check and accomplish your variable declarations here: + Dim seen As ??? + Dim pivot As ??? + Rem pivot = values(p) - REM Tausche das Pivot-Element an den start + Rem Tausche das Pivot-Element an den start values(p) = values(start) values(start) = pivot p = start - REM Beginning and end of the remaining unknown range + Rem Beginning and end of the remaining unknown range start = start + 1 stop = stop - 1 - REM Still unseen elements? - DO WHILE stop >= start + Rem Still unseen elements? + Do While stop >= start seen = values(start) - IF values(start) <= pivot THEN - REM Swap pivot element with start element + If values(start) <= pivot Then + Rem Swap pivot element with start element values(p) = seen values(start) = pivot p = p + 1 start = start + 1 - ELSE - REM Put the found element to the end of the unknown area + Else + Rem Put the found element to the end of the unknown area values(start) = values(stop) values(stop) = seen stop = stop - 1 - END IF - LOOP + End If + Loop return p -END FUNCTION -REM -REM Checks whether or not the passed-in array is (ascendingly) sorted. -REM TODO: Check (and specify if needed) the argument and result types! -FUNCTION testSorted(numbers) AS bool - REM TODO: declare your variables here: - REM DIM isSorted AS - REM DIM i AS - REM +End Function +Rem +Rem Checks whether or not the passed-in array is (ascendingly) sorted. +Rem TODO: Check (and specify if needed) the argument and result types! +Function testSorted(numbers) As bool + Rem TODO: Check and accomplish your variable declarations here: + Dim isSorted As boolean + Dim i As Integer + Rem isSorted = true i = 0 - REM As we compare with the following element, we must stop at the penultimate index - DO WHILE isSorted AND (i <= length(numbers)-2) - REM Is there an inversion? - IF numbers(i) > numbers(i+1) THEN + Rem As we compare with the following element, we must stop at the penultimate index + Do While isSorted AND (i <= length(numbers)-2) + Rem Is there an inversion? + If numbers(i) > numbers(i+1) Then isSorted = false - ELSE + Else i = i + 1 - END IF - LOOP + End If + Loop return isSorted -END FUNCTION -REM -REM Runs through the array heap and converts it to a max-heap -REM in a bottom-up manner, i.e. starts above the "leaf" level -REM (index >= length(heap) div 2) and goes then up towards -REM the root. -REM TODO: Check (and specify if needed) the argument and result types! -FUNCTION buildMaxHeap(heap) - REM TODO: declare your variables here: - REM DIM lgth AS - REM DIM k AS - REM +End Function +Rem +Rem Runs through the array heap and converts it to a max-heap +Rem in a bottom-up manner, i.e. starts above the "leaf" level +Rem (index >= length(heap) div 2) and goes then up towards +Rem the root. +Rem TODO: Check (and specify if needed) the argument and result types! +Function buildMaxHeap(heap) + Rem TODO: Check and accomplish your variable declarations here: + Dim lgth As Integer + Dim k As Integer + Rem lgth = length(heap) - FOR k = lgth / 2 - 1 TO 0 STEP -1 - CALL maxHeapify(heap, k, lgth) - NEXT k - RETURN 0 -END FUNCTION -REM -REM Recursively sorts a subrange of the given array 'values´. -REM start is the first index of the subsequence to be sorted, -REM stop is the index BEHIND the subsequence to be sorted. -REM TODO: Check (and specify if needed) the argument and result types! -FUNCTION quickSort(values, start, stop) - REM TODO: declare your variables here: - REM DIM p AS - REM - REM At least 2 elements? (Less don't make sense.) - IF stop >= start + 2 THEN - REM Select a pivot element, be p its index. - REM (here: randomly chosen element out of start ... stop-1) + For k = lgth / 2 - 1 To 0 Step -1 + Call maxHeapify(heap, k, lgth) + Next k + Return 0 +End Function +Rem +Rem Recursively sorts a subrange of the given array 'values´. +Rem start is the first index of the subsequence to be sorted, +Rem stop is the index BEHIND the subsequence to be sorted. +Rem TODO: Check (and specify if needed) the argument and result types! +Function quickSort(values, start, stop) + Rem TODO: Check and accomplish your variable declarations here: + Dim p As ??? + Rem + Rem At least 2 elements? (Less don't make sense.) + If stop >= start + 2 Then + Rem Select a pivot element, be p its index. + Rem (here: randomly chosen element out of start ... stop-1) p = random(stop-start) + start - REM Partition the array into smaller and greater elements - REM Get the resulting (and final) position of the pivot element - CALL p = partition(values, start, stop, p) - REM Sort subsequances separately and independently ... + Rem Partition the array into smaller and greater elements + Rem Get the resulting (and final) position of the pivot element + p = partition(values, start, stop, p) + Rem Sort subsequances separately and independently ... - REM ========================================================== - REM ================= START PARALLEL SECTION ================= - REM ========================================================== - REM TODO: add the necessary code to run the threads concurrently + Rem ========================================================== + Rem ================= START PARALLEL SECTION ================= + Rem ========================================================== + Rem TODO: add the necessary code to run the threads concurrently - REM ----------------- START THREAD 0 ----------------- - REM Sort left (lower) array part - CALL quickSort(values, start, p) - REM ------------------ END THREAD 0 ------------------ + Rem ----------------- START THREAD 0 ----------------- + Rem Sort left (lower) array part + Call quickSort(values, start, p) + Rem ------------------ END THREAD 0 ------------------ - REM ----------------- START THREAD 1 ----------------- - REM Sort right (higher) array part - CALL quickSort(values, p+1, stop) - REM ------------------ END THREAD 1 ------------------ + Rem ----------------- START THREAD 1 ----------------- + Rem Sort right (higher) array part + Call quickSort(values, p+1, stop) + Rem ------------------ END THREAD 1 ------------------ - REM ========================================================== - REM ================== END PARALLEL SECTION ================== - REM ========================================================== + Rem ========================================================== + Rem ================== END PARALLEL SECTION ================== + Rem ========================================================== - END IF - RETURN 0 -END FUNCTION -REM -REM Sorts the array 'values´ of numbers according to he heap sort -REM algorithm -REM TODO: Check (and specify if needed) the argument and result types! -FUNCTION heapSort(values) - REM TODO: declare your variables here: - REM DIM maximum AS - REM DIM k AS - REM DIM heapRange AS - REM - CALL buildMaxHeap(values) + End If + Return 0 +End Function +Rem +Rem Sorts the array 'values´ of numbers according to he heap sort +Rem algorithm +Rem TODO: Check (and specify if needed) the argument and result types! +Function heapSort(values) + Rem TODO: Check and accomplish your variable declarations here: + Dim maximum As ??? + Dim k As Integer + Dim heapRange As Integer + Rem + Call buildMaxHeap(values) heapRange = length(values) - FOR k = heapRange - 1 TO 1 STEP -1 + For k = heapRange - 1 To 1 Step -1 heapRange = heapRange - 1 - REM Swap the maximum value (root of the heap) to the heap end + Rem Swap the maximum value (root of the heap) to the heap end maximum = values(0) values(0) = values(heapRange) values(heapRange) = maximum - CALL maxHeapify(values, 0, heapRange) - NEXT k - RETURN 0 -END FUNCTION + Call maxHeapify(values, 0, heapRange) + Next k + Return 0 +End Function diff --git a/samples/export/BASIC1/TextDemo.bas b/samples/export/BASIC1/TextDemo.bas new file mode 100644 index 00000000..d1fb1d2e --- /dev/null +++ b/samples/export/BASIC1/TextDemo.bas @@ -0,0 +1,1135 @@ +Rem Demo program for routine drawText() +Rem Asks the user to enter a text, a wanted text height and colour, +Rem and then draws this string onto the turtle screen. Places every +Rem entered text to a new line. +Rem Generated by Structorizer 3.30-03 +Rem +Rem Copyright (C) 2019-10-10 Kay Gürtzig +Rem License: GPLv3-link +Rem GNU General Public License (V 3) +Rem https://www.gnu.org/licenses/gpl.html +Rem http://www.gnu.de/documents/gpl.de.html +Rem +Rem +Rem program TextDemo +Rem TODO: Check and accomplish your variable declarations here: +Dim y As Integer +Dim text As ??? +Dim height As ??? +Dim colour As ??? +Rem +PRINT "This is a demo program for text writing with Turleizer." +showTurtle() +penDown() +y = 0 +Do + PRINT "Enter some text (empty string to exit)"; : INPUT text + Rem Make sure the content is interpreted as string + text = "" + text + If text <> "" Then + Do + PRINT "Height of the text (pixels)"; : INPUT height + Loop Until height >= 5 + Do + PRINT "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"; : INPUT colour + Loop Until colour >= 1 AND colour <= 10 + y = y + height + 2 + gotoXY(0, y - 2) + Call drawText(text, height, colour) + End If +Loop Until text = "" +gotoXY(0, y + 15) +Call drawText("Thank you, bye.", 10, 4) +hideTurtle() +End +Rem +Rem Draws a blank for font height h, ignoring the colorNo +Rem TODO: Check (and specify if needed) the argument and result types! +Sub blank(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Rem + width = h/2.0 + penUp() + right(90) + forward(width) : Rem color = ffffff + left(90) +End Sub +Rem +Rem TODO: Check (and specify if needed) the argument and result types! +Sub forward(len, color) + Rem TODO: Check and accomplish your variable declarations here: + Rem + Select Case color + Case 1 + forward(len) : Rem color = ffffff + Case 2 + forward(len) : Rem color = ff8080 + Case 3 + forward(len) : Rem color = ffff80 + Case 4 + forward(len) : Rem color = 80ff80 + Case 5 + forward(len) : Rem color = 80ffff + Case 6 + forward(len) : Rem color = 0080ff + Case 7 + forward(len) : Rem color = ff80c0 + Case 8 + forward(len) : Rem color = c0c0c0 + Case 9 + forward(len) : Rem color = ff8000 + Case 10 + forward(len) : Rem color = 8080ff + End Select +End Sub +Rem +Rem Draws letter A in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterA(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle As double + Dim hypo As double + Rem + width = h/2.0 + hypo = sqrt(h*h + width*width/4.0) + rotAngle = toDegrees(atan(width/2.0/h)) + right(rotAngle) + Call forward(hypo/2.0, colorNo) + right(90 - rotAngle) + Call forward(width/2.0, colorNo) + penUp() + backward(width/2.0) : Rem color = ffffff + penDown() + left(90 - rotAngle) + Call forward(hypo/2.0, colorNo) + left(2*rotAngle) + Call forward(-hypo, colorNo) + right(rotAngle) +End Sub +Rem +Rem Draws letter L in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterL(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Rem + width = h/2.0 + Call forward(h, colorNo) + penUp() + backward(h) : Rem color = ffffff + right(90) + penDown() + Call forward(width, colorNo) + left(90) +End Sub +Rem +Rem Draws letter N in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterN(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle As double + Dim hypo As double + Rem + width = h/2.0 + hypo = sqrt(width*width + h*h) + rotAngle = toDegrees(atan(width/h)) + Call forward(h, colorNo) + left(rotAngle) + Call forward(-hypo, colorNo) + right(rotAngle) + Call forward(h, colorNo) + penUp() + backward(h) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter E in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterE(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Rem + width = h/2.0 + Call forward(h, colorNo) + right(90) + Call forward(width, colorNo) + right(90) + penUp() + forward(h/2.0) : Rem color = ffffff + right(90) + penDown() + Call forward(width, colorNo) + left(90) + penUp() + forward(h/2.0) : Rem color = ffffff + left(90) + penDown() + Call forward(width, colorNo) + left(90) +End Sub +Rem +Rem Draws letter V in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterV(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle As double + Dim hypo As double + Rem + width = h/2.0 + hypo = sqrt(h*h + width*width/4.0) + rotAngle = toDegrees(atan(width/2.0/h)) + penUp() + forward(h) : Rem color = ffffff + left(rotAngle) + penDown() + Call forward(-hypo, colorNo) + right(2*rotAngle) + Call forward(hypo, colorNo) + penUp() + left(rotAngle) + backward(h) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter F in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterF(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Rem + width = h/2.0 + Call forward(h, colorNo) + right(90) + Call forward(width, colorNo) + right(90) + penUp() + forward(h/2.0) : Rem color = ffffff + right(90) + penDown() + Call forward(width, colorNo) + left(90) + penUp() + forward(h/2.0) : Rem color = ffffff + left(90) + forward(width) : Rem color = ffffff + penDown() + left(90) +End Sub +Rem +Rem Draws letter I in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterI(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim c As ??? + Dim b As ??? + Rem + Rem Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Cathetus of the corner triangle outside the octagon + c = b / sqrt(2.0) + penUp() + right(90) + forward(c) : Rem color = ffffff + penDown() + Call forward(b, colorNo) + penUp() + backward(b/2.0) : Rem color = ffffff + left(90) + penDown() + Call forward(h, colorNo) + penUp() + right(90) + backward(b/2.0) : Rem color = ffffff + penDown() + Call forward(b, colorNo) + penUp() + forward(b/2 + c) : Rem color = ffffff + left(90) + backward(h) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter W in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterW(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width_3 As ??? + Dim width As ??? + Dim rotAngle As double + Dim hypo As double + Rem + width = h/2.0 + width_3 = width/3.0 + hypo = sqrt(width_3*width_3 + h*h) + rotAngle = toDegrees(atan(width_3/h)) + penUp() + forward(h) : Rem color = ffffff + left(rotAngle) + penDown() + Call forward(-hypo, colorNo) + right(2*rotAngle) + Call forward(hypo, colorNo) + penUp() + left(90+rotAngle) + forward(width_3) : Rem color = ffffff + right(90-rotAngle) + penDown() + Call forward(-hypo, colorNo) + right(2*rotAngle) + Call forward(hypo, colorNo) + penUp() + left(rotAngle) + backward(h) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws nEdges edges of a regular n-polygon with edge length a +Rem counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub polygonPart(a AS double, n AS integer, ctrclkws AS boolean, nEdges AS integer, color AS Integer) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As ??? + Dim k As Integer + Rem + rotAngle = 360.0/n + If ctrclkws Then + rotAngle = -rotAngle + End If + For k = 1 To nEdges + right(rotAngle) + Call forward(a, color) + Next k +End Sub +Rem +Rem Draws letter H in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterH(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Rem + width = h/2.0 + Call forward(h, colorNo) + penUp() + right(90) + forward(width) : Rem color = ffffff + right(90) + penDown() + Call forward(h/2.0, colorNo) + right(90) + Call forward(width, colorNo) + penUp() + backward(width) : Rem color = ffffff + left(90) + penDown() + Call forward(h/2.0, colorNo) + left(180) +End Sub +Rem +Rem Draws letter K in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterK(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim diag As ??? + Rem + width = h/2.0 + diag = h/sqrt(2.0) + Call forward(h, colorNo) + penUp() + right(90) + forward(width) : Rem color = ffffff + right(135) + penDown() + Call forward(diag, colorNo) + left(90) + Call forward(diag, colorNo) + left(135) +End Sub +Rem +Rem Draws letter Y in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterY(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle As double + Dim hypo As ??? + Rem + width = h/2.0 + hypo = sqrt(width*width + h*h)/2.0 + rotAngle = toDegrees(atan(width/h)) + penUp() + forward(h) : Rem color = ffffff + left(rotAngle) + penDown() + Call forward(-hypo, colorNo) + right(rotAngle) + penUp() + backward(h/2.0) : Rem color = ffffff + penDown() + Call forward(h/2.0, colorNo) + right(rotAngle) + Call forward(hypo, colorNo) + left(rotAngle) + penUp() + backward(h) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter X in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterX(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle As double + Dim hypo As double + Rem + width = h/2.0 + hypo = sqrt(width*width + h*h) + rotAngle = toDegrees(atan(width/h)) + right(rotAngle) + Call forward(hypo, colorNo) + penUp() + left(90+rotAngle) + forward(width) : Rem color = ffffff + right(90-rotAngle) + penDown() + Call forward(-hypo, colorNo) + right(rotAngle) +End Sub +Rem +Rem Draws letter T in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterT(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Rem + width = h/2.0 + penUp() + forward(h) : Rem color = ffffff + penDown() + right(90) + Call forward(width, colorNo) + penUp() + backward(width/2.0) : Rem color = ffffff + penDown() + right(90) + Call forward(h, colorNo) + left(90) + penUp() + forward(width/2.0) : Rem color = ffffff + penDown() + left(90) +End Sub +Rem +Rem Draws letter Z in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterZ(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle As double + Dim hypo As double + Rem + width = h/2.0 + hypo = sqrt(width*width + h*h) + rotAngle = toDegrees(atan(width/h)) + penUp() + forward(h) : Rem color = ffffff + right(90) + penDown() + Call forward(width, colorNo) + left(90-rotAngle) + Call forward(-hypo, colorNo) + right(90-rotAngle) + Call forward(width, colorNo) + left(90) +End Sub +Rem +Rem Draws letter M in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterM(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle As double + Dim hypo As ??? + Rem + width = h/2.0 + hypo = sqrt(width*width + h*h)/2.0 + rotAngle = toDegrees(atan(width/h)) + Call forward(h, colorNo) + left(rotAngle) + Call forward(-hypo, colorNo) + right(2*rotAngle) + Call forward(hypo, colorNo) + left(rotAngle) + Call forward(-h, colorNo) +End Sub +Rem +Rem Draws letter Q in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterQ(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As Integer + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + Rem 360°/8 + rotAngle = 45 + penUp() + forward(c) : Rem color = ffffff + penDown() + right(180) + Rem Counterclockwise draw 4 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, true, 4, colorNo) + Call forward(b + 2*c, colorNo) + Rem Counterclockwise draw 4 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, true, 4, colorNo) + Call forward(b + 2*c, colorNo) + penUp() + forward(c) : Rem color = ffffff + left(90) + forward(b + 2*c) : Rem color = ffffff + right(rotAngle) + backward(b) : Rem color = ffffff + penDown() + Call forward(b, colorNo) + left(90 + rotAngle) +End Sub +Rem +Rem Draws letter O in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterO(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim c As ??? + Dim b As ??? + Rem + Rem Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Cathetus of the corner triangle outside the octagon + c = b / sqrt(2.0) + penUp() + forward(c) : Rem color = ffffff + penDown() + right(180) + Rem Counterclockwise draw 4 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, true, 4, colorNo) + Call forward(b + 2*c, colorNo) + Rem Counterclockwise draw 4 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, true, 4, colorNo) + Call forward(b + 2*c, colorNo) + penUp() + forward(c) : Rem color = ffffff + left(90) + forward(b + 2*c) : Rem color = ffffff + penDown() + left(90) +End Sub +Rem +Rem Draws a question mark in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub qstnMk(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As Integer + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + Rem 360°/8 + rotAngle = 45 + penUp() + forward(h-c) : Rem color = ffffff + penDown() + Rem Counterclockwise draw 5 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, false, 5, colorNo) + Call forward(c, colorNo) + left(rotAngle) + Call forward(b/2.0, colorNo) + penUp() + forward(c) : Rem color = ffffff + left(90) + forward(c/2.0) : Rem color = ffffff + penDown() + Rem Counterclockwise draw all 4 edges of a squarfe with edge length c + Rem in the colour endcoded by colorNo + Call polygonPart(c, 4, false, 4, colorNo) + penUp() + forward((c + b)/2.0) : Rem color = ffffff + left(90) + backward(c) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter C in the colour encoded by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterC(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As Integer + Dim c As ??? + Dim b As ??? + Rem + Rem Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Cathetus of the outer trinagle at the octagon corner + c = b / sqrt(2.0) + Rem 360°/8 + rotAngle = 45 + penUp() + forward(c) : Rem color = ffffff + penDown() + right(180) + Rem Clockwise draws 3 edges of an octagon with edge length b in the colour + Rem encoded by colorNo + Call polygonPart(b, 8, true, 3, colorNo) + left(rotAngle) + penUp() + forward(2*b + 2*c) : Rem color = ffffff + penDown() + Rem Counterclockwise draws 4 edges of an octagon with edge length b + Rem iin the colour encoded by colorNo + Call polygonPart(b, 8, true, 4, colorNo) + Call forward(b + 2*c, colorNo) + penUp() + forward(c) : Rem color = ffffff + left(90) + Call forward(b + 2*c, colorNo) + penDown() + left(90) +End Sub +Rem +Rem Draws a comma in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub comma(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As double + Dim hypo As ??? + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + rotAngle = toDegrees(atan(0.5)) + hypo = c * sqrt(1.25) + penUp() + right(90) + forward((c+b)/2.0 + c) : Rem color = ffffff + penDown() + Rem Counterclockwise draw 3 edges of a square with edge length c + Rem in the colour endcoded by colorNo + Call polygonPart(c, 4, true, 3, colorNo) + left(90) + Call forward(c/2.0, colorNo) + right(90) + Call forward(c, colorNo) + left(180 - rotAngle) + Call forward(hypo, colorNo) + penUp() + right(90 - rotAngle) + forward((c + b)/2.0) : Rem color = ffffff + left(90) + penDown() +End Sub +Rem +Rem Zeichnet den Buchstaben R von der Turtleposition aus +Rem mit Zeilenhöhe h +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterR(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As Integer + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + Rem 360°/8 + rotAngle = 45 + Call forward(h, colorNo) + right(90) + Call forward(c+b, colorNo) + Rem Clockwise draw 4 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, false, 4, colorNo) + Call forward(c, colorNo) + left(90 + rotAngle) + Call forward(sqrt(2.0)*(b + 2*c), colorNo) + left(90 + rotAngle) +End Sub +Rem +Rem Draws a full stop in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub fullSt(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + penUp() + right(90) + forward((c+b)/2.0 + c) : Rem color = ffffff + penDown() + Rem Counterclockwise draw all 4 edges of a squarfe with edge length c + Rem in the colour endcoded by colorNo + Call polygonPart(c, 4, true, 4, colorNo) + penUp() + forward((c + b)/2.0) : Rem color = ffffff + left(90) + penDown() +End Sub +Rem +Rem Draws letter G in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterG(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim c As ??? + Dim b As ??? + Rem + Rem Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Cathetus of the corner triangle outside the octagon. + c = b / sqrt(2.0) + penUp() + forward(c) : Rem color = ffffff + penDown() + right(180) + Rem Counterclockwise draw 4 edges of an octagon with edge length b in + Rem the colour encoded by colorNo + Call polygonPart(b, 8, true, 4, colorNo) + Call forward(c, colorNo) + left(90) + Call forward(b/2.0 + c, colorNo) + penUp() + backward(b/2.0 + c) : Rem color = ffffff + right(90) + forward(b + c) : Rem color = ffffff + penDown() + Rem Counterclockwise draw 4 edges of an octagon with edge length b in + Rem the colour encoded by colorNo + Call polygonPart(b, 8, true, 4, colorNo) + Call forward(b + 2*c, colorNo) + penUp() + forward(c) : Rem color = ffffff + left(90) + Call forward(b + 2*c, colorNo) + penDown() + left(90) +End Sub +Rem +Rem Draws letter D in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterD(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + Call forward(h, colorNo) + right(90) + Call forward(c+b, colorNo) + Rem Clockwise draw 2 edges of an octagon with edge length b in the colour + Rem encoded by colorNo + Call polygonPart(b, 8, false, 2, colorNo) + Call forward(b + 2*c, colorNo) + Rem Clockwise draw 2 edges of an octagon with edge length b in the colour + Rem encoded by colorNo + Call polygonPart(b, 8, false, 2, colorNo) + Call forward(c, colorNo) + penUp() + left(180) + forward(b + 2*c) : Rem color = ffffff + penDown() + left(90) +End Sub +Rem +Rem Draws letter P in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterP(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim c As ??? + Dim b As ??? + Rem + Rem Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Cathetus of the corner triangle outside the octagon + c = b / sqrt(2.0) + Call forward(h, colorNo) + right(90) + Call forward(c+b, colorNo) + Rem Clockwise draw 4 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, false, 4, colorNo) + Call forward(c, colorNo) + penUp() + backward(b + 2*c) : Rem color = ffffff + left(90) + forward(b + 2*c) : Rem color = ffffff + penDown() + left(180) +End Sub +Rem +Rem Draws letter U in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterU(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As Integer + Dim c As ??? + Dim b As ??? + Rem + Rem edge length of a regular octagon + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + Rem 360°/8 + rotAngle = 45 + penUp() + forward(c) : Rem color = ffffff + penDown() + Call forward(h - c, colorNo) + penUp() + backward(h-c) : Rem color = ffffff + penDown() + right(180) + Rem Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + Call polygonPart(b, 8, true, 3, colorNo) + left(rotAngle) + Call forward(h - c, colorNo) + penUp() + backward(h) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter J in colour encoded by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterJ(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As Integer + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + Rem 360°/8 + rotAngle = 45 + penUp() + forward(c) : Rem color = ffffff + penDown() + right(180) + Rem Counterclockwise draw 3 edges of an octagon with edge length b in + Rem the colour encoded by colorNo + Call polygonPart(b, 8, true, 3, colorNo) + left(rotAngle) + Call forward(h - c, colorNo) + penUp() + backward(h) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter S in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterS(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim rotAngle As Integer + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + Rem 360°/8 + rotAngle = 45 + penUp() + forward(c) : Rem color = ffffff + penDown() + right(180) + Rem Counterclockwise draw 6 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, true, 6, colorNo) + Rem Clockwise draw 5 edges of an octagon with edge length b + Rem in the colour endcoded by colorNo + Call polygonPart(b, 8, false, 5, colorNo) + right(rotAngle) + penUp() + forward(2*b + 3*c) : Rem color = ffffff + penDown() + left(180) +End Sub +Rem +Rem Draws a dummy character (small centered square) with font height h and +Rem the colour encoded by colorNo +Rem TODO: Check (and specify if needed) the argument and result types! +Sub charDummy(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim d As ??? + Dim c As ??? + Dim b As ??? + Rem + width = h / 2.0 + Rem Octagon edge length (here: edge lengzh of the square) + b = width / (sqrt(2.0) + 1) + Rem Cathetus of the corner triangle outside the octagon + c = (width - b) / 2.0 + d = b / sqrt(2.0) + penUp() + forward(h/2.0-b/2.0) : Rem color = ffffff + right(90) + forward(c) : Rem color = ffffff + right(90) + penDown() + Rem Draws the square with edge length b + Call polygonPart(b, 4, true, 4, colorNo) + penUp() + left(90) + forward(b + c) : Rem color = ffffff + left(90) + backward(h/2.0-b/2.0) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws an exclamation mark in the colour encoded by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub exclMk(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim width As ??? + Dim rotAngle2 As double + Dim rotAngle As Integer + Dim length2 As ??? + Dim length1 As ??? + Dim hypo As double + Dim c As ??? + Dim b As ??? + Rem + Rem Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Eckenlänge außen am Achteck + c = b / sqrt(2.0) + width = h/2.0 + length1 = h - (b+c)/2.0 + length2 = length1 - 2*c + hypo = sqrt(width*width/16.0 + length2*length2) + Rem 360°/8 + rotAngle = 45 + rotAngle2 = toDegrees(atan(width/4.0/length2)) + penUp() + forward(length1) : Rem color = ffffff + right(90) + forward(width/2.0) : Rem color = ffffff + left(90 + rotAngle) + penDown() + Rem Clockwise draw 5 edges of an octagon with edge length b/2 + Rem in the colour endcoded by colorNo + Call polygonPart(b/2.0, 8, false, 5, colorNo) + right(rotAngle2) + Call forward(hypo, colorNo) + left(2*rotAngle2) + Call forward(-hypo, colorNo) + penUp() + forward(hypo) : Rem color = ffffff + right(rotAngle2) + forward(c) : Rem color = ffffff + left(90) + forward(c/2.0) : Rem color = ffffff + penDown() + Rem Counterclockwise draw all 4 edges of a squarfe with edge length c + Rem in the colour endcoded by colorNo + Call polygonPart(c, 4, false, 4, colorNo) + penUp() + forward((c + b)/2.0) : Rem color = ffffff + left(90) + backward(c) : Rem color = ffffff + penDown() +End Sub +Rem +Rem Draws letter B in colour specified by colorNo with font height h +Rem from the current turtle position. +Rem TODO: Check (and specify if needed) the argument and result types! +Sub letterB(h, colorNo) + Rem TODO: Check and accomplish your variable declarations here: + Dim c As ??? + Dim b As ??? + Rem + Rem Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1) + Rem Cathetus of the outer corner triangle of the octagon + c = b / sqrt(2.0) + Call forward(h, colorNo) + right(90) + Call forward(c+b, colorNo) + Rem Clockwise draw 4 edges of an octagon with edge length b + Call polygonPart(b, 8, false, 4, colorNo) + Call forward(c, colorNo) + penUp() + left(180) + forward(b + c) : Rem color = ffffff + penDown() + Rem Clockwise draw 4 edges of an octagon with edge length b + Call polygonPart(b, 8, false, 4, colorNo) + Call forward(c, colorNo) + penUp() + left(180) + forward(b + 2*c) : Rem color = ffffff + penDown() + left(90) +End Sub +Rem +Rem Has the turtle draw the given string 'text´ with font height 'h´ (in +Rem pixels) and the colour coded by integer 'c´ from the current Turtle +Rem position to the Turtle canvas. If the turtle looks North then +Rem the text will be written rightwards. In the event, the turtle will be +Rem placed behind the text in original orientation (such that the next text +Rem would be written like a continuation. Colour codes: +Rem 1 = black +Rem 2 = red +Rem 3 = yellow +Rem 4 = green +Rem 5 = cyan +Rem 6 = blue +Rem 7 = pink +Rem 8 = grey +Rem 9 = orange +Rem 10 = violet +Rem All letters (ASCII) will be converted to uppercase, digits cannot +Rem be represented, the set of representable special characters is: +Rem '.', ',', '!', '?'. Other characters will be shown as a small +Rem centred square (dummy character). +Rem TODO: Check (and specify if needed) the argument and result types! +Sub drawText(text AS String, h AS integer, c AS integer) + Rem TODO: Check and accomplish your variable declarations here: + Dim letter As String + Dim k As Integer + Dim gap As ??? + Rem + gap = h/10.0 + For k = 1 To length(text) + letter = uppercase(copy(text, k, 1)) + If letter = "," Then + Call comma(h,c) + Else + Rem "," cannot be chacked against because the comma is misinterpreted + Rem as selector list separator. + Select Case letter + Case "A" + Call letterA(h,c) + Case "B" + Call letterB(h,c) + Case "C" + Call letterC(h,c) + Case "D" + Call letterD(h,c) + Case "E" + Call letterE(h,c) + Case "F" + Call letterF(h,c) + Case "G" + Call letterG(h,c) + Case "H" + Call letterH(h,c) + Case "I" + Call letterI(h,c) + Case "J" + Call letterJ(h,c) + Case "K" + Call letterK(h,c) + Case "L" + Call letterL(h,c) + Case "M" + Call letterM(h,c) + Case "N" + Call letterN(h,c) + Case "O" + Call letterO(h,c) + Case "P" + Call letterP(h,c) + Case "Q" + Call letterQ(h,c) + Case "R" + Call letterR(h,c) + Case "S" + Call letterS(h,c) + Case "T" + Call letterT(h,c) + Case "U" + Call letterU(h,c) + Case "V" + Call letterV(h,c) + Case "W" + Call letterW(h,c) + Case "X" + Call letterX(h,c) + Case "Y" + Call letterY(h,c) + Case "Z" + Call letterZ(h,c) + Case " " + Call blank(h,c) + Case "!" + Call exclMk(h,c) + Case "?" + Call qstnMk(h,c) + Case "." + Call fullSt(h,c) + Case Else + Call charDummy(h,c) + End Select + End If + right(90) + penUp() + forward(gap) : Rem color = ffffff + penDown() + left(90) + Next k +End Sub diff --git a/samples/export/C#/ELIZA_2.3.cs b/samples/export/C#/ELIZA_2.3.cs new file mode 100644 index 00000000..39c0e9f6 --- /dev/null +++ b/samples/export/C#/ELIZA_2.3.cs @@ -0,0 +1,488 @@ +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2018-05-14 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// + +using System; + + +/// +/// Concept and lisp implementation published by Joseph Weizenbaum (MIT): +/// "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +/// Computational Linguistis 1(1966)9, pp. 36-45 +/// Revision history: +/// 2016-10-06 Initial version +/// 2017-03-29 Two diagrams updated (comments translated to English) +/// 2017-03-29 More keywords and replies added +/// 2019-03-14 Replies and mapping reorganised for easier maintenance +/// 2019-03-15 key map joined from keyword array and index map +/// 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +/// 2019-11-28 New global type "History" (to ensure a homogenous array) +/// +public class ELIZA { + + + + + + + + + + + + + + // histArray contains the most recent user replies as ring buffer; + // histIndex is the index where the next reply is to be stored (= index of the oldest + // cached user reply). + // Note: The depth of the history is to be specified by initializing a variable of this type, + // e.g. for a history of depth 5: + // myhistory <- History{{"", "", "", "", ""}, 0} + public struct History{ + public string[] histArray; + public int histIndex; + public History(string[] p_histArray, int p_histIndex) + { + histArray = p_histArray; + histIndex = p_histIndex; + } + }; + + // Associates a key word in the text with an index in the reply ring array + public struct KeyMapEntry{ + public string keyword; + public int index; + public KeyMapEntry(string p_keyword, int p_index) + { + keyword = p_keyword; + index = p_index; + } + }; + + + /// array of command line arguments + public static void Main(string[] args) { + + // BEGIN initialization for "History" + // END initialization for "History" + // BEGIN initialization for "KeyMapEntry" + // END initialization for "KeyMapEntry" + + // TODO: Check and accomplish variable declarations: + string varPart; + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + string userInput; + string reply; + int posAster; + int[] offsets; + bool isRepeated; + bool isGone; + int[] findInfo; + + + // TODO: You may have to modify input instructions, + // possibly by enclosing Console.ReadLine() calls with + // Parse methods according to the variable type, e.g.: + // i = int.Parse(Console.ReadLine()); + + // Title information + Console.WriteLine("************* ELIZA **************"); + Console.WriteLine("* Original design by J. Weizenbaum"); + Console.WriteLine("**********************************"); + Console.WriteLine("* Adapted for Basic on IBM PC by"); + Console.WriteLine("* - Patricia Danielson"); + Console.WriteLine("* - Paul Hashfield"); + Console.WriteLine("**********************************"); + Console.WriteLine("* Adapted for Structorizer by"); + Console.WriteLine("* - Kay Gürtzig / FH Erfurt 2016"); + Console.WriteLine("* Version: 2.3 (2019-11-28)"); + Console.WriteLine("* (Requires at least Structorizer 3.30-03 to run)"); + Console.WriteLine("**********************************"); + // Stores the last five inputs of the user in a ring buffer, + // the second component is the rolling (over-)write index. + History history = new History(new string[]{"", "", "", "", ""}, 0); + const string[,] replies = setupReplies(); + const string[,] reflexions = setupReflexions(); + const string[,] byePhrases = setupGoodByePhrases(); + const KeyMapEntry[] keyMap = setupKeywords(); + offsets[length(keyMap)-1] = 0; + isGone = false; + // Starter + Console.WriteLine("Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?"); + do { + userInput = Console.ReadLine(); + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + userInput = normalizeInput(userInput); + isGone = checkGoodBye(userInput, byePhrases); + if (! isGone) { + reply = "Please don\'t repeat yourself!"; + isRepeated = checkRepetition(history, userInput); + if (! isRepeated) { + findInfo = findKeyword(keyMap, userInput); + ??? keyIndex = findInfo[0]; + if (keyIndex < 0) { + // Should never happen... + keyIndex = length(keyMap)-1; + } + KeyMapEntry entry = keyMap[keyIndex]; + // Variable part of the reply + varPart = ""; + if (length(entry.keyword) > 0) { + varPart = conjugateStrings(userInput, entry.keyword, findInfo[1], reflexions); + } + ??? replyRing = replies[entry.index]; + reply = replyRing[offsets[keyIndex]]; + offsets[keyIndex] = (offsets[keyIndex] + 1) % length(replyRing); + posAster = pos("*", reply); + if (posAster > 0) { + if (varPart == " ") { + reply = "You will have to elaborate more for me to help you."; + } + else { + delete(reply, posAster, 1); + insert(varPart, reply, posAster); + } + } + reply = adjustSpelling(reply); + } + Console.WriteLine(reply); + } + } while (!(isGone)); + } + + /// + /// Cares for correct letter case among others + /// + /// TODO + /// TODO + private static string adjustSpelling(string sentence) { + // TODO: Check and accomplish variable declarations: + string word; + string start; + string result; + int position; + + + result = sentence; + position = 1; + while ((position <= length(sentence)) && (copy(sentence, position, 1) == " ")) { + position = position + 1; + } + if (position <= length(sentence)) { + start = copy(sentence, 1, position); + delete(result, 1, position); + insert(uppercase(start), result, 1); + } + foreach (String word in new String[]{" i ", " i\'"}) { + position = pos(word, result); + while (position > 0) { + delete(result, position+1, 1); + insert("I", result, position+1); + position = pos(word, result); + } + } + + return result; + } + + /// + /// Checks whether the given text contains some kind of + /// good-bye phrase inducing the end of the conversation + /// and if so writes a correspding good-bye message and + /// returns true, otherwise false + /// + /// TODO + /// TODO + /// TODO + private static bool checkGoodBye(string text, string[,] phrases) { + // TODO: Check and accomplish variable declarations: + bool saidBye; + string[] pair; + + + foreach (@string pair in phrases) { + if (pos(pair[0], text) > 0) { + saidBye = true; + Console.WriteLine(pair[1]); + return true; + } + } + return false; + } + + /// + /// Checks whether newInput has occurred among the recently cached + /// input strings in the histArray component of history and updates the history. + /// + /// TODO + /// TODO + /// TODO + private static bool checkRepetition(History history, string newInput) { + // TODO: Check and accomplish variable declarations: + int histDepth; + bool hasOccurred; + + + hasOccurred = false; + if (length(newInput) > 4) { + histDepth = length(history.histArray); + for (int i = 0; i <= histDepth-1; i += (1)) { + if (newInput == history.histArray[i]) { + hasOccurred = true; + } + } + history.histArray[history.histIndex] = newInput; + history.histIndex = (history.histIndex + 1) % (histDepth); + } + return hasOccurred; + } + + /// + /// + /// TODO + /// TODO + /// TODO + /// TODO + /// TODO + private static string conjugateStrings(string sentence, string key, int keyPos, string[,] flexions) { + // TODO: Check and accomplish variable declarations: + string right; + string result; + int position; + string[] pair; + string left; + + + result = " " + copy(sentence, keyPos + length(key), length(sentence)) + " "; + foreach (@string pair in flexions) { + left = ""; + right = result; + position = pos(pair[0], right); + while (position > 0) { + left = left + copy(right, 1, position-1) + pair[1]; + right = copy(right, position + length(pair[0]), length(right)); + position = pos(pair[0], right); + } + result = left + right; + } + // Eliminate multiple spaces + position = pos(" ", result); + while (position > 0) { + result = copy(result, 1, position-1) + copy(result, position+1, length(result)); + position = pos(" ", result); + } + + return result; + } + + /// + /// Looks for the occurrence of the first of the strings + /// contained in keywords within the given sentence (in + /// array order). + /// Returns an array of + /// 0: the index of the first identified keyword (if any, otherwise -1), + /// 1: the position inside sentence (0 if not found) + /// + /// TODO + /// TODO + /// TODO + private static int[] findKeyword(const array of KeyMapEntry keyMap, string sentence) { + // TODO: Check and accomplish variable declarations: + int[] result; + int position; + int i; + + + // Contains the index of the keyword and its position in sentence + result = new int[]{-1, 0}; + i = 0; + while ((result[0] < 0) && (i < length(keyMap))) { + KeyMapEntry entry = keyMap[i]; + position = pos(entry.keyword, sentence); + if (position > 0) { + result[0] = i; + result[1] = position; + } + i = i+1; + } + + return result; + } + + /// + /// Converts the sentence to lowercase, eliminates all + /// interpunction (i.e. ',', '.', ';'), and pads the + /// sentence among blanks + /// + /// TODO + /// TODO + private static string normalizeInput(string sentence) { + // TODO: Check and accomplish variable declarations: + string symbol; + string result; + int position; + + + sentence = lowercase(sentence); + foreach (String symbol in new String[]{'.', ',', ';', '!', '?'}) { + position = pos(symbol, sentence); + while (position > 0) { + sentence = copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)); + position = pos(symbol, sentence); + } + } + result = " " + sentence + " "; + + return result; + } + + /// + /// + /// TODO + private static string[,] setupGoodByePhrases() { + // TODO: Check and accomplish variable declarations: + string[,] phrases; + + + phrases[0] = new string[]{" shut", "Okay. If you feel that way I\'ll shut up. ... Your choice."}; + phrases[1] = new string[]{"bye", "Well, let\'s end our talk for now. See you later. Bye."}; + return phrases; + } + + /// + /// The lower the index the higher the rank of the keyword (search is sequential). + /// The index of the first keyword found in a user sentence maps to a respective + /// reply ring as defined in `setupReplies()´. + /// + /// TODO + private static KeyMapEntry[] setupKeywords() { + // TODO: Check and accomplish variable declarations: + // The empty key string (last entry) is the default clause - will always be found + KeyMapEntry[] keywords; + + + // The empty key string (last entry) is the default clause - will always be found + keywords[39] = new KeyMapEntry("", 29); + keywords[0] = new KeyMapEntry("can you ", 0); + keywords[1] = new KeyMapEntry("can i ", 1); + keywords[2] = new KeyMapEntry("you are ", 2); + keywords[3] = new KeyMapEntry("you\'re ", 2); + keywords[4] = new KeyMapEntry("i don't ", 3); + keywords[5] = new KeyMapEntry("i feel ", 4); + keywords[6] = new KeyMapEntry("why don\'t you ", 5); + keywords[7] = new KeyMapEntry("why can\'t i ", 6); + keywords[8] = new KeyMapEntry("are you ", 7); + keywords[9] = new KeyMapEntry("i can\'t ", 8); + keywords[10] = new KeyMapEntry("i am ", 9); + keywords[11] = new KeyMapEntry("i\'m ", 9); + keywords[12] = new KeyMapEntry("you ", 10); + keywords[13] = new KeyMapEntry("i want ", 11); + keywords[14] = new KeyMapEntry("what ", 12); + keywords[15] = new KeyMapEntry("how ", 12); + keywords[16] = new KeyMapEntry("who ", 12); + keywords[17] = new KeyMapEntry("where ", 12); + keywords[18] = new KeyMapEntry("when ", 12); + keywords[19] = new KeyMapEntry("why ", 12); + keywords[20] = new KeyMapEntry("name ", 13); + keywords[21] = new KeyMapEntry("cause ", 14); + keywords[22] = new KeyMapEntry("sorry ", 15); + keywords[23] = new KeyMapEntry("dream ", 16); + keywords[24] = new KeyMapEntry("hello ", 17); + keywords[25] = new KeyMapEntry("hi ", 17); + keywords[26] = new KeyMapEntry("maybe ", 18); + keywords[27] = new KeyMapEntry(" no", 19); + keywords[28] = new KeyMapEntry("your ", 20); + keywords[29] = new KeyMapEntry("always ", 21); + keywords[30] = new KeyMapEntry("think ", 22); + keywords[31] = new KeyMapEntry("alike ", 23); + keywords[32] = new KeyMapEntry("yes ", 24); + keywords[33] = new KeyMapEntry("friend ", 25); + keywords[34] = new KeyMapEntry("computer", 26); + keywords[35] = new KeyMapEntry("bot ", 26); + keywords[36] = new KeyMapEntry("smartphone", 27); + keywords[37] = new KeyMapEntry("father ", 28); + keywords[38] = new KeyMapEntry("mother ", 28); + return keywords; + } + + /// + /// Returns an array of pairs of mutualy substitutable + /// + /// TODO + private static string[,] setupReflexions() { + // TODO: Check and accomplish variable declarations: + string[,] reflexions; + + + reflexions[0] = new string[]{" are ", " am "}; + reflexions[1] = new string[]{" were ", " was "}; + reflexions[2] = new string[]{" you ", " I "}; + reflexions[3] = new string[]{" your", " my"}; + reflexions[4] = new string[]{" i\'ve ", " you\'ve "}; + reflexions[5] = new string[]{" i\'m ", " you\'re "}; + reflexions[6] = new string[]{" me ", " you "}; + reflexions[7] = new string[]{" my ", " your "}; + reflexions[8] = new string[]{" i ", " you "}; + reflexions[9] = new string[]{" am ", " are "}; + return reflexions; + } + + /// + /// This routine sets up the reply rings addressed by the key words defined in + /// routine `setupKeywords()´ and mapped hitherto by the cross table defined + /// in `setupMapping()´ + /// + /// TODO + private static string[,] setupReplies() { + // TODO: Check and accomplish variable declarations: + string[,] setupReplies; + + + String[,] replies; + // We start with the highest index for performance reasons + // (is to avoid frequent array resizing) + replies[29] = new string[]{"Say, do you have any psychological problems?", "What does that suggest to you?", "I see.", "I'm not sure I understand you fully.", "Come come elucidate your thoughts.", "Can you elaborate on that?", "That is quite interesting."}; + replies[0] = new string[]{"Don't you believe that I can*?", "Perhaps you would like to be like me?", "You want me to be able to*?"}; + replies[1] = new string[]{"Perhaps you don't want to*?", "Do you want to be able to*?"}; + replies[2] = new string[]{"What makes you think I am*?", "Does it please you to believe I am*?", "Perhaps you would like to be*?", "Do you sometimes wish you were*?"}; + replies[3] = new string[]{"Don't you really*?", "Why don't you*?", "Do you wish to be able to*?", "Does that trouble you*?"}; + replies[4] = new string[]{"Do you often feel*?", "Are you afraid of feeling*?", "Do you enjoy feeling*?"}; + replies[5] = new string[]{"Do you really believe I don't*?", "Perhaps in good time I will*.", "Do you want me to*?"}; + replies[6] = new string[]{"Do you think you should be able to*?", "Why can't you*?"}; + replies[7] = new string[]{"Why are you interested in whether or not I am*?", "Would you prefer if I were not*?", "Perhaps in your fantasies I am*?"}; + replies[8] = new string[]{"How do you know you can't*?", "Have you tried?", "Perhaps you can now*."}; + replies[9] = new string[]{"Did you come to me because you are*?", "How long have you been*?", "Do you believe it is normal to be*?", "Do you enjoy being*?"}; + replies[10] = new string[]{"We were discussing you--not me.", "Oh, I*.", "You're not really talking about me, are you?"}; + replies[11] = new string[]{"What would it mean to you if you got*?", "Why do you want*?", "Suppose you soon got*...", "What if you never got*?", "I sometimes also want*."}; + replies[12] = new string[]{"Why do you ask?", "Does that question interest you?", "What answer would please you the most?", "What do you think?", "Are such questions on your mind often?", "What is it that you really want to know?", "Have you asked anyone else?", "Have you asked such questions before?", "What else comes to mind when you ask that?"}; + replies[13] = new string[]{"Names don't interest me.", "I don't care about names -- please go on."}; + replies[14] = new string[]{"Is that the real reason?", "Don't any other reasons come to mind?", "Does that reason explain anything else?", "What other reasons might there be?"}; + replies[15] = new string[]{"Please don't apologize!", "Apologies are not necessary.", "What feelings do you have when you apologize?", "Don't be so defensive!"}; + replies[16] = new string[]{"What does that dream suggest to you?", "Do you dream often?", "What persons appear in your dreams?", "Are you disturbed by your dreams?"}; + replies[17] = new string[]{"How do you do ...please state your problem."}; + replies[18] = new string[]{"You don't seem quite certain.", "Why the uncertain tone?", "Can't you be more positive?", "You aren't sure?", "Don't you know?"}; + replies[19] = new string[]{"Are you saying no just to be negative?", "You are being a bit negative.", "Why not?", "Are you sure?", "Why no?"}; + replies[20] = new string[]{"Why are you concerned about my*?", "What about your own*?"}; + replies[21] = new string[]{"Can you think of a specific example?", "When?", "What are you thinking of?", "Really, always?"}; + replies[22] = new string[]{"Do you really think so?", "But you are not sure you*?", "Do you doubt you*?"}; + replies[23] = new string[]{"In what way?", "What resemblance do you see?", "What does the similarity suggest to you?", "What other connections do you see?", "Could there really be some connection?", "How?", "You seem quite positive."}; + replies[24] = new string[]{"Are you sure?", "I see.", "I understand."}; + replies[25] = new string[]{"Why do you bring up the topic of friends?", "Do your friends worry you?", "Do your friends pick on you?", "Are you sure you have any friends?", "Do you impose on your friends?", "Perhaps your love for friends worries you."}; + replies[26] = new string[]{"Do computers worry you?", "Are you talking about me in particular?", "Are you frightened by machines?", "Why do you mention computers?", "What do you think machines have to do with your problem?", "Don't you think computers can help people?", "What is it about machines that worries you?"}; + replies[27] = new string[]{"Do you sometimes feel uneasy without a smartphone?", "Have you had these phantasies before?", "Does the world seem more real for you via apps?"}; + replies[28] = new string[]{"Tell me more about your family.", "Who else in your family*?", "What does family relations mean for you?", "Come on, How old are you?"}; + setupReplies = replies; + + return setupReplies; + } + +} diff --git a/samples/export/C#/SORTING_TEST_MAIN.cs b/samples/export/C#/SORTING_TEST_MAIN.cs index 0f0d7bf7..725858b2 100644 --- a/samples/export/C#/SORTING_TEST_MAIN.cs +++ b/samples/export/C#/SORTING_TEST_MAIN.cs @@ -1,4 +1,4 @@ -// Generated by Structorizer 3.30-02 +// Generated by Structorizer 3.30-03 // // Copyright (C) 2019-10-02 Kay Gürtzig // License: GPLv3-link @@ -20,10 +20,10 @@ public class SORTING_TEST_MAIN { // =========== START PARALLEL WORKER DEFINITIONS ============ - class Worker4f085546_0{ + class Worker247e34b9_0{ // TODO: Check and accomplish the member declarations here - private /*type?*/ values1; - public Worker4f085546_0(/*type?*/ values1) + private int[] values1; + public Worker247e34b9_0(int[] values1) { this.values1 = values1; } @@ -33,11 +33,11 @@ public void DoWork() } }; - class Worker4f085546_1{ + class Worker247e34b9_1{ // TODO: Check and accomplish the member declarations here - private /*type?*/ values2; - private /*type?*/ elementCount; - public Worker4f085546_1(/*type?*/ values2, /*type?*/ elementCount) + private ???[] values2; + private ??? elementCount; + public Worker247e34b9_1(???[] values2, ??? elementCount) { this.values2 = values2; this.elementCount = elementCount; @@ -48,10 +48,10 @@ public void DoWork() } }; - class Worker4f085546_2{ + class Worker247e34b9_2{ // TODO: Check and accomplish the member declarations here - private /*type?*/ values3; - public Worker4f085546_2(/*type?*/ values3) + private ???[] values3; + public Worker247e34b9_2(???[] values3) { this.values3 = values3; } @@ -68,12 +68,12 @@ public void DoWork() // =========== START PARALLEL WORKER DEFINITIONS ============ - class Worker3dfab37d_0{ + class Worker7fed1521_0{ // TODO: Check and accomplish the member declarations here - private /*type?*/ values; - private /*type?*/ start; - private /*type?*/ p; - public Worker3dfab37d_0(/*type?*/ values, /*type?*/ start, /*type?*/ p) + private ??? values; + private ??? start; + private ??? p; + public Worker7fed1521_0(??? values, ??? start, ??? p) { this.values = values; this.start = start; @@ -86,12 +86,12 @@ public void DoWork() } }; - class Worker3dfab37d_1{ + class Worker7fed1521_1{ // TODO: Check and accomplish the member declarations here - private /*type?*/ values; - private /*type?*/ p; - private /*type?*/ stop; - public Worker3dfab37d_1(/*type?*/ values, /*type?*/ p, /*type?*/ stop) + private ??? values; + private ??? p; + private ??? stop; + public Worker7fed1521_1(??? values, ??? p, ??? stop) { this.values = values; this.p = p; @@ -112,10 +112,13 @@ public void DoWork() public static void Main(string[] args) { // TODO: Check and accomplish variable declarations: - ??? values3; - ??? values2; - ??? values1; + ???[] values3; + ???[] values2; + int[] values1; ??? show; + bool ok3; + bool ok2; + bool ok1; ??? modus; ??? elementCount; @@ -144,7 +147,7 @@ public static void Main(string[] args) { break; } } - // Kopiere das Array für exakte Vergleichbarkeit + // Copy the array for exact comparability for (int i = 0; i <= elementCount-1; i += (1)) { values2[i] = values1[i]; values3[i] = values1[i]; @@ -154,21 +157,21 @@ public static void Main(string[] args) { // ================= START PARALLEL SECTION ================= // ========================================================== { - Worker4f085546_0 worker4f085546_0 = new Worker4f085546_0(values1); - Thread thr4f085546_0 = new Thread(worker4f085546_0.DoWork); - thr4f085546_0.Start(); + Worker247e34b9_0 worker247e34b9_0 = new Worker247e34b9_0(values1); + Thread thr247e34b9_0 = new Thread(worker247e34b9_0.DoWork); + thr247e34b9_0.Start(); - Worker4f085546_1 worker4f085546_1 = new Worker4f085546_1(values2, elementCount); - Thread thr4f085546_1 = new Thread(worker4f085546_1.DoWork); - thr4f085546_1.Start(); + Worker247e34b9_1 worker247e34b9_1 = new Worker247e34b9_1(values2, elementCount); + Thread thr247e34b9_1 = new Thread(worker247e34b9_1.DoWork); + thr247e34b9_1.Start(); - Worker4f085546_2 worker4f085546_2 = new Worker4f085546_2(values3); - Thread thr4f085546_2 = new Thread(worker4f085546_2.DoWork); - thr4f085546_2.Start(); + Worker247e34b9_2 worker247e34b9_2 = new Worker247e34b9_2(values3); + Thread thr247e34b9_2 = new Thread(worker247e34b9_2.DoWork); + thr247e34b9_2.Start(); - thr4f085546_0.Join(); - thr4f085546_1.Join(); - thr4f085546_2.Join(); + thr247e34b9_0.Join(); + thr247e34b9_1.Join(); + thr247e34b9_2.Join(); } // ========================================================== // ================== END PARALLEL SECTION ================== @@ -203,16 +206,16 @@ public static void Main(string[] args) { /// subrange. /// /// TODO - private static void bubbleSort(/*type?*/ values) { + private static void bubbleSort(??? values) { // TODO: Check and accomplish variable declarations: - ende = length(values) - 2; + ??? ende = length(values) - 2; do { // The index of the most recent swapping (-1 means no swapping done). - posSwapped = -1; + ??? posSwapped = -1; for (int i = 0; i <= ende; i += (1)) { if (values[i] > values[i+1]) { - temp = values[i]; + ??? temp = values[i]; values[i] = values[i+1]; values[i+1] = temp; posSwapped = i; @@ -231,14 +234,14 @@ private static void bubbleSort(/*type?*/ values) { /// TODO /// TODO /// TODO - private static void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) { + private static void maxHeapify(??? heap, ??? i, ??? range) { // TODO: Check and accomplish variable declarations: // Indices of left and right child of node i - right = (i+1) * 2; - left = right - 1; + ??? right = (i+1) * 2; + ??? left = right - 1; // Index of the (local) maximum - max = i; + ??? max = i; if (left < range && heap[left] > heap[i]) { max = left; } @@ -246,7 +249,7 @@ private static void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) { max = right; } if (max != i) { - temp = heap[i]; + ??? temp = heap[i]; heap[i] = heap[max]; heap[max] = temp; maxHeapify(heap, max, range); @@ -268,10 +271,10 @@ private static void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) { /// TODO /// TODO /// TODO - private static int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /*type?*/ p) { + private static int partition(??? values, ??? start, ??? stop, ??? p) { // TODO: Check and accomplish variable declarations: - pivot = values[p]; + ??? pivot = values[p]; // Tausche das Pivot-Element an den start values[p] = values[start]; values[start] = pivot; @@ -281,7 +284,7 @@ private static int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, stop = stop - 1; // Still unseen elements? while (stop >= start) { - seen = values[start]; + ??? seen = values[start]; if (values[start] <= pivot) { // Swap pivot element with start element values[p] = seen; @@ -304,7 +307,7 @@ private static int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /// /// TODO /// TODO - private static bool testSorted(/*type?*/ numbers) { + private static bool testSorted(??? numbers) { // TODO: Check and accomplish variable declarations: bool isSorted; int i; @@ -333,7 +336,7 @@ private static bool testSorted(/*type?*/ numbers) { /// /// TODO /// TODO - private static int buildMaxHeap(/*type?*/ heap) { + private static int buildMaxHeap(??? heap) { // TODO: Check and accomplish variable declarations: int lgth; @@ -355,14 +358,14 @@ private static int buildMaxHeap(/*type?*/ heap) { /// TODO /// TODO /// TODO - private static int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) { + private static int quickSort(??? values, ??? start, ??? stop) { // TODO: Check and accomplish variable declarations: // At least 2 elements? (Less don't make sense.) if (stop >= start + 2) { // Select a pivot element, be p its index. // (here: randomly chosen element out of start ... stop-1) - p = random(stop-start) + start; + ??? p = random(stop-start) + start; // Partition the array into smaller and greater elements // Get the resulting (and final) position of the pivot element // Partition the array into smaller and greater elements @@ -374,16 +377,16 @@ private static int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) // ================= START PARALLEL SECTION ================= // ========================================================== { - Worker3dfab37d_0 worker3dfab37d_0 = new Worker3dfab37d_0(values, start, p); - Thread thr3dfab37d_0 = new Thread(worker3dfab37d_0.DoWork); - thr3dfab37d_0.Start(); + Worker7fed1521_0 worker7fed1521_0 = new Worker7fed1521_0(values, start, p); + Thread thr7fed1521_0 = new Thread(worker7fed1521_0.DoWork); + thr7fed1521_0.Start(); - Worker3dfab37d_1 worker3dfab37d_1 = new Worker3dfab37d_1(values, p, stop); - Thread thr3dfab37d_1 = new Thread(worker3dfab37d_1.DoWork); - thr3dfab37d_1.Start(); + Worker7fed1521_1 worker7fed1521_1 = new Worker7fed1521_1(values, p, stop); + Thread thr7fed1521_1 = new Thread(worker7fed1521_1.DoWork); + thr7fed1521_1.Start(); - thr3dfab37d_0.Join(); - thr3dfab37d_1.Join(); + thr7fed1521_0.Join(); + thr7fed1521_1.Join(); } // ========================================================== // ================== END PARALLEL SECTION ================== @@ -400,7 +403,7 @@ private static int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) /// /// TODO /// TODO - private static int heapSort(/*type?*/ values) { + private static int heapSort(??? values) { // TODO: Check and accomplish variable declarations: int heapRange; @@ -410,7 +413,7 @@ private static int heapSort(/*type?*/ values) { for (int k = heapRange - 1; k >= 1; k += (-1)) { heapRange = heapRange - 1; // Swap the maximum value (root of the heap) to the heap end - maximum = values[0]; + ??? maximum = values[0]; values[0] = values[heapRange]; values[heapRange] = maximum; maxHeapify(values, 0, heapRange); diff --git a/samples/export/C#/TextDemo.cs b/samples/export/C#/TextDemo.cs new file mode 100644 index 00000000..4b87bd61 --- /dev/null +++ b/samples/export/C#/TextDemo.cs @@ -0,0 +1,1302 @@ +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2019-10-10 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// + +using System; + + +/// +/// Demo program for routine drawText() +/// Asks the user to enter a text, a wanted text height and colour, +/// and then draws this string onto the turtle screen. Places every +/// entered text to a new line. +/// +public class TextDemo { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /// array of command line arguments + public static void Main(string[] args) { + + // TODO: Check and accomplish variable declarations: + int y; + ??? height; + ??? colour; + + + // TODO: You may have to modify input instructions, + // possibly by enclosing Console.ReadLine() calls with + // Parse methods according to the variable type, e.g.: + // i = int.Parse(Console.ReadLine()); + + Console.WriteLine("This is a demo program for text writing with Turleizer."); + showTurtle(); + penDown(); + y = 0; + do { + Console.Write("Enter some text (empty string to exit)"); text = Console.ReadLine(); + // Make sure the content is interpreted as string + ??? text = "" + text; + if (text != "") { + do { + Console.Write("Height of the text (pixels)"); height = Console.ReadLine(); + } while (!(height >= 5)); + do { + Console.Write("Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"); colour = Console.ReadLine(); + } while (!(colour >= 1 && colour <= 10)); + y = y + height + 2; + gotoXY(0, y - 2); + drawText(text, height, colour); + } + } while (!(text == "")); + gotoXY(0, y + 15); + drawText("Thank you, bye.", 10, 4); + hideTurtle(); + } + + /// + /// Draws a blank for font height h, ignoring the colorNo + /// + /// TODO + /// TODO + private static void blank(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + penUp(); + right(90); + forward(width); // color = ffffff + left(90); + } + + /// + /// + /// TODO + /// TODO + private static void forward(??? len, ??? color) { + // TODO: Check and accomplish variable declarations: + + switch (color) { + case 1: + forward(len); // color = ffffff + break; + case 2: + forward(len); // color = ff8080 + break; + case 3: + forward(len); // color = ffff80 + break; + case 4: + forward(len); // color = 80ff80 + break; + case 5: + forward(len); // color = 80ffff + break; + case 6: + forward(len); // color = 0080ff + break; + case 7: + forward(len); // color = ff80c0 + break; + case 8: + forward(len); // color = c0c0c0 + break; + case 9: + forward(len); // color = ff8000 + break; + case 10: + forward(len); // color = 8080ff + break; + } + } + + /// + /// Draws letter A in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterA(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(h*h + width*width/4.0); + rotAngle = toDegrees(atan(width/2.0/h)); + right(rotAngle); + forward(hypo/2.0, colorNo); + right(90 - rotAngle); + forward(width/2.0, colorNo); + penUp(); + backward(width/2.0); // color = ffffff + penDown(); + left(90 - rotAngle); + forward(hypo/2.0, colorNo); + left(2*rotAngle); + forward(-hypo, colorNo); + right(rotAngle); + } + + /// + /// Draws letter E in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterE(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); // color = ffffff + left(90); + penDown(); + forward(width, colorNo); + left(90); + } + + /// + /// Draws letter F in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterF(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); // color = ffffff + left(90); + forward(width); // color = ffffff + penDown(); + left(90); + } + + /// + /// Draws letter H in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterH(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + penUp(); + right(90); + forward(width); // color = ffffff + right(90); + penDown(); + forward(h/2.0, colorNo); + right(90); + forward(width, colorNo); + penUp(); + backward(width); // color = ffffff + left(90); + penDown(); + forward(h/2.0, colorNo); + left(180); + } + + /// + /// Draws letter I in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterI(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / sqrt(2.0); + penUp(); + right(90); + forward(c); // color = ffffff + penDown(); + forward(b, colorNo); + penUp(); + backward(b/2.0); // color = ffffff + left(90); + penDown(); + forward(h, colorNo); + penUp(); + right(90); + backward(b/2.0); // color = ffffff + penDown(); + forward(b, colorNo); + penUp(); + forward(b/2 + c); // color = ffffff + left(90); + backward(h); // color = ffffff + penDown(); + } + + /// + /// Draws letter K in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterK(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + ??? diag = h/sqrt(2.0); + forward(h, colorNo); + penUp(); + right(90); + forward(width); // color = ffffff + right(135); + penDown(); + forward(diag, colorNo); + left(90); + forward(diag, colorNo); + left(135); + } + + /// + /// Draws letter L in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterL(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + penUp(); + backward(h); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); + } + + /// + /// Draws letter M in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterM(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + ??? width = h/2.0; + ??? hypo = sqrt(width*width + h*h)/2.0; + rotAngle = toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + left(rotAngle); + forward(-h, colorNo); + } + + /// + /// Draws letter N in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterN(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(rotAngle); + forward(h, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); + } + + /// + /// Draws letter T in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterT(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + penUp(); + forward(h); // color = ffffff + penDown(); + right(90); + forward(width, colorNo); + penUp(); + backward(width/2.0); // color = ffffff + penDown(); + right(90); + forward(h, colorNo); + left(90); + penUp(); + forward(width/2.0); // color = ffffff + penDown(); + left(90); + } + + /// + /// Draws letter V in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterV(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(h*h + width*width/4.0); + rotAngle = toDegrees(atan(width/2.0/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); // color = ffffff + penDown(); + } + + /// + /// Draws letter W in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterW(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + ??? width_3 = width/3.0; + hypo = sqrt(width_3*width_3 + h*h); + rotAngle = toDegrees(atan(width_3/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width_3); // color = ffffff + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); // color = ffffff + penDown(); + } + + /// + /// Draws letter X in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterX(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + right(rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width); // color = ffffff + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); + } + + /// + /// Draws letter Y in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterY(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + ??? width = h/2.0; + ??? hypo = sqrt(width*width + h*h)/2.0; + rotAngle = toDegrees(atan(width/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); + penUp(); + backward(h/2.0); // color = ffffff + penDown(); + forward(h/2.0, colorNo); + right(rotAngle); + forward(hypo, colorNo); + left(rotAngle); + penUp(); + backward(h); // color = ffffff + penDown(); + } + + /// + /// Draws letter Z in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterZ(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + penUp(); + forward(h); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90-rotAngle); + forward(-hypo, colorNo); + right(90-rotAngle); + forward(width, colorNo); + left(90); + } + + /// + /// Draws nEdges edges of a regular n-polygon with edge length a + /// counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. + /// + /// TODO + /// TODO + /// TODO + /// TODO + /// TODO + private static void polygonPart(double a, int n, bool ctrclkws, int nEdges, int color) { + // TODO: Check and accomplish variable declarations: + + ??? rotAngle = 360.0/n; + if (ctrclkws) { + rotAngle = -rotAngle; + } + for (int k = 1; k <= nEdges; k += (1)) { + right(rotAngle); + forward(a, color); + } + } + + /// + /// Draws a dummy character (small centered square) with font height h and + /// the colour encoded by colorNo + /// + /// TODO + /// TODO + private static void charDummy(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h / 2.0; + // Octagon edge length (here: edge lengzh of the square) + ??? b = width / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = (width - b) / 2.0; + ??? d = b / sqrt(2.0); + penUp(); + forward(h/2.0-b/2.0); // color = ffffff + right(90); + forward(c); // color = ffffff + right(90); + penDown(); + // Draws the square with edge length b + polygonPart(b, 4, true, 4, colorNo); + penUp(); + left(90); + forward(b + c); // color = ffffff + left(90); + backward(h/2.0-b/2.0); // color = ffffff + penDown(); + } + + /// + /// Draws a comma in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void comma(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + rotAngle = toDegrees(atan(0.5)); + ??? hypo = c * sqrt(1.25); + penUp(); + right(90); + forward((c+b)/2.0 + c); // color = ffffff + penDown(); + // Counterclockwise draw 3 edges of a square with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 3, colorNo); + left(90); + forward(c/2.0, colorNo); + right(90); + forward(c, colorNo); + left(180 - rotAngle); + forward(hypo, colorNo); + penUp(); + right(90 - rotAngle); + forward((c + b)/2.0); // color = ffffff + left(90); + penDown(); + } + + /// + /// Draws an exclamation mark in the colour encoded by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void exclMk(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle2; + // 360°/8 + int rotAngle; + double hypo; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + ??? width = h/2.0; + ??? length1 = h - (b+c)/2.0; + ??? length2 = length1 - 2*c; + hypo = sqrt(width*width/16.0 + length2*length2); + // 360°/8 + rotAngle = 45; + rotAngle2 = toDegrees(atan(width/4.0/length2)); + penUp(); + forward(length1); // color = ffffff + right(90); + forward(width/2.0); // color = ffffff + left(90 + rotAngle); + penDown(); + // Clockwise draw 5 edges of an octagon with edge length b/2 + // in the colour endcoded by colorNo + polygonPart(b/2.0, 8, false, 5, colorNo); + right(rotAngle2); + forward(hypo, colorNo); + left(2*rotAngle2); + forward(-hypo, colorNo); + penUp(); + forward(hypo); // color = ffffff + right(rotAngle2); + forward(c); // color = ffffff + left(90); + forward(c/2.0); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + backward(c); // color = ffffff + penDown(); + } + + /// + /// Draws a full stop in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void fullSt(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + penUp(); + right(90); + forward((c+b)/2.0 + c); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + penDown(); + } + + /// + /// Draws letter B in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterB(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the outer corner triangle of the octagon + ??? c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + c); // color = ffffff + penDown(); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); + } + + /// + /// Draws letter C in the colour encoded by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterC(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the outer trinagle at the octagon corner + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Clockwise draws 3 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + penUp(); + forward(2*b + 2*c); // color = ffffff + penDown(); + // Counterclockwise draws 4 edges of an octagon with edge length b + // iin the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); + } + + /// + /// Draws letter D in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterD(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + forward(b + 2*c, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); + } + + /// + /// Draws letter G in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterG(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon. + ??? c = b / sqrt(2.0); + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(c, colorNo); + left(90); + forward(b/2.0 + c, colorNo); + penUp(); + backward(b/2.0 + c); // color = ffffff + right(90); + forward(b + c); // color = ffffff + penDown(); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); + } + + /// + /// Draws letter J in colour encoded by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterJ(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 3 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); + } + + /// + /// Draws letter O in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterO(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / sqrt(2.0); + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); + } + + /// + /// Draws letter P in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterP(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + backward(b + 2*c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + penDown(); + left(180); + } + + /// + /// Draws letter Q in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterQ(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + right(rotAngle); + backward(b); // color = ffffff + penDown(); + forward(b, colorNo); + left(90 + rotAngle); + } + + /// + /// Zeichnet den Buchstaben R von der Turtleposition aus + /// mit Zeilenhöhe h + /// + /// TODO + /// TODO + private static void letterR(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + left(90 + rotAngle); + forward(sqrt(2.0)*(b + 2*c), colorNo); + left(90 + rotAngle); + } + + /// + /// Draws letter S in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterS(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 6 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 6, colorNo); + // Clockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + right(rotAngle); + penUp(); + forward(2*b + 3*c); // color = ffffff + penDown(); + left(180); + } + + /// + /// Draws letter U in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void letterU(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // edge length of a regular octagon + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + forward(h - c, colorNo); + penUp(); + backward(h-c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); + } + + /// + /// Draws a question mark in colour specified by colorNo with font height h + /// from the current turtle position. + /// + /// TODO + /// TODO + private static void qstnMk(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(h-c); // color = ffffff + penDown(); + // Counterclockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + forward(c, colorNo); + left(rotAngle); + forward(b/2.0, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(c/2.0); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + backward(c); // color = ffffff + penDown(); + } + + /// + /// Has the turtle draw the given string 'text´ with font height 'h´ (in + /// pixels) and the colour coded by integer 'c´ from the current Turtle + /// position to the Turtle canvas. If the turtle looks North then + /// the text will be written rightwards. In the event, the turtle will be + /// placed behind the text in original orientation (such that the next text + /// would be written like a continuation. Colour codes: + /// 1 = black + /// 2 = red + /// 3 = yellow + /// 4 = green + /// 5 = cyan + /// 6 = blue + /// 7 = pink + /// 8 = grey + /// 9 = orange + /// 10 = violet + /// All letters (ASCII) will be converted to uppercase, digits cannot + /// be represented, the set of representable special characters is: + /// '.', ',', '!', '?'. Other characters will be shown as a small + /// centred square (dummy character). + /// + /// TODO + /// TODO + /// TODO + private static void drawText(string text, int h, int c) { + // TODO: Check and accomplish variable declarations: + string letter; + + + ??? gap = h/10.0; + for (int k = 1; k <= length(text); k += (1)) { + letter = uppercase(copy(text, k, 1)); + if (letter == ",") { + comma(h,c); + } + else { + // "," cannot be chacked against because the comma is misinterpreted + // as selector list separator. + switch (letter) { + case "A": + letterA(h,c); + break; + case "B": + letterB(h,c); + break; + case "C": + letterC(h,c); + break; + case "D": + letterD(h,c); + break; + case "E": + letterE(h,c); + break; + case "F": + letterF(h,c); + break; + case "G": + letterG(h,c); + break; + case "H": + letterH(h,c); + break; + case "I": + letterI(h,c); + break; + case "J": + letterJ(h,c); + break; + case "K": + letterK(h,c); + break; + case "L": + letterL(h,c); + break; + case "M": + letterM(h,c); + break; + case "N": + letterN(h,c); + break; + case "O": + letterO(h,c); + break; + case "P": + letterP(h,c); + break; + case "Q": + letterQ(h,c); + break; + case "R": + letterR(h,c); + break; + case "S": + letterS(h,c); + break; + case "T": + letterT(h,c); + break; + case "U": + letterU(h,c); + break; + case "V": + letterV(h,c); + break; + case "W": + letterW(h,c); + break; + case "X": + letterX(h,c); + break; + case "Y": + letterY(h,c); + break; + case "Z": + letterZ(h,c); + break; + case " ": + blank(h,c); + break; + case "!": + exclMk(h,c); + break; + case "?": + qstnMk(h,c); + break; + case ".": + fullSt(h,c); + break; + default: + charDummy(h,c); + } + } + right(90); + penUp(); + forward(gap); // color = ffffff + penDown(); + left(90); + } + } + +} diff --git a/samples/export/C++/ELIZA_2.3.cpp b/samples/export/C++/ELIZA_2.3.cpp new file mode 100644 index 00000000..eefa0afe --- /dev/null +++ b/samples/export/C++/ELIZA_2.3.cpp @@ -0,0 +1,587 @@ +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2018-05-14 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// +#include + +// histArray contains the most recent user replies as ring buffer; +// histIndex is the index where the next reply is to be stored (= index of the oldest +// cached user reply). +// Note: The depth of the history is to be specified by initializing a variable of this type, +// e.g. for a history of depth 5: +// myhistory <- History{{"", "", "", "", ""}, 0} +struct History { + string[] histArray; + int histIndex; +}; + +// Associates a key word in the text with an index in the reply ring array +struct KeyMapEntry { + string keyword; + int index; +}; + + +// Cares for correct letter case among others +// function adjustSpelling(sentence: string): string +// TODO Revise the return type and declare the parameters! +string adjustSpelling(string sentence) +{ + // TODO: Check and accomplish variable declarations: + string word; + string start; + string result; + int position; + + + result = sentence; + position = 1; + while ((position <= length(sentence)) && (copy(sentence, position, 1) == " ")) { + position = position + 1; + } + if (position <= length(sentence)) { + start = copy(sentence, 1, position); + delete(result, 1, position); + insert(uppercase(start), result, 1); + } + for (auto word : {" i ", " i\'"}) { + position = pos(word, result); + while (position > 0) { + delete(result, position+1, 1); + insert("I", result, position+1); + position = pos(word, result); + } + } + + return result; +} + +// Checks whether the given text contains some kind of +// good-bye phrase inducing the end of the conversation +// and if so writes a correspding good-bye message and +// returns true, otherwise false +// function checkGoodBye(text: string; phrases: array of array[0..1] of string): boolean +// TODO Revise the return type and declare the parameters! +bool checkGoodBye(string text, string phrases[][2]) +{ + // TODO: Check and accomplish variable declarations: + bool saidBye; + string pair[]; + + + for (auto pair : phrases) { + if (pos(pair[0], text) > 0) { + saidBye = true; + std::cout << pair[1] << std::endl; + return true; + } + } + return false; +} + +// Checks whether newInput has occurred among the recently cached +// input strings in the histArray component of history and updates the history. +// function checkRepetition(history: History; newInput: string): boolean +// TODO Revise the return type and declare the parameters! +bool checkRepetition(History history, string newInput) +{ + // TODO: Check and accomplish variable declarations: + int histDepth; + bool hasOccurred; + + + hasOccurred = false; + if (length(newInput) > 4) { + histDepth = length(history.histArray); + for (int i = 0; i <= histDepth-1; i += (1)) { + if (newInput == history.histArray[i]) { + hasOccurred = true; + } + } + history.histArray[history.histIndex] = newInput; + history.histIndex = (history.histIndex + 1) % (histDepth); + } + return hasOccurred; +} + +// function conjugateStrings(sentence: string; key: string; keyPos: integer; flexions: array of array[0..1] of string): string +// TODO Revise the return type and declare the parameters! +string conjugateStrings(string sentence, string key, int keyPos, string flexions[][2]) +{ + // TODO: Check and accomplish variable declarations: + string right; + string result; + int position; + string pair[]; + string left; + + + result = " " + copy(sentence, keyPos + length(key), length(sentence)) + " "; + for (auto pair : flexions) { + left = ""; + right = result; + position = pos(pair[0], right); + while (position > 0) { + left = left + copy(right, 1, position-1) + pair[1]; + right = copy(right, position + length(pair[0]), length(right)); + position = pos(pair[0], right); + } + result = left + right; + } + // Eliminate multiple spaces + position = pos(" ", result); + while (position > 0) { + result = copy(result, 1, position-1) + copy(result, position+1, length(result)); + position = pos(" ", result); + } + + return result; +} + +// Looks for the occurrence of the first of the strings +// contained in keywords within the given sentence (in +// array order). +// Returns an array of +// 0: the index of the first identified keyword (if any, otherwise -1), +// 1: the position inside sentence (0 if not found) +// function findKeyword(const keyMap: array of KeyMapEntry; sentence: string): array[0..1] of integer +// C++ may not permit to return arrays like this - find an other way to pass the result! +// TODO Revise the return type and declare the parameters! +int[2] findKeyword(const array of KeyMapEntry keyMap, string sentence) +{ + // TODO: Check and accomplish variable declarations: + int result[2]; + int position; + int i; + + + result[0] = -1; + result[1] = 0; + i = 0; + while ((result[0] < 0) && (i < length(keyMap))) { + KeyMapEntry entry = keyMap[i]; + position = pos(entry.keyword, sentence); + if (position > 0) { + result[0] = i; + result[1] = position; + } + i = i+1; + } + + return result; +} + +// Converts the sentence to lowercase, eliminates all +// interpunction (i.e. ',', '.', ';'), and pads the +// sentence among blanks +// function normalizeInput(sentence: string): string +// TODO Revise the return type and declare the parameters! +string normalizeInput(string sentence) +{ + // TODO: Check and accomplish variable declarations: + string symbol; + string result; + int position; + + + sentence = lowercase(sentence); + for (auto symbol : {'.', ',', ';', '!', '?'}) { + position = pos(symbol, sentence); + while (position > 0) { + sentence = copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)); + position = pos(symbol, sentence); + } + } + result = " " + sentence + " "; + + return result; +} + +// function setupGoodByePhrases(): array of array[0..1] of string +// C++ may not permit to return arrays like this - find an other way to pass the result! +// TODO Revise the return type and declare the parameters! +string[][2] setupGoodByePhrases() +{ + // TODO: Check and accomplish variable declarations: + string phrases[][2]; + + + phrases[0][0] = " shut"; + phrases[0][1] = "Okay. If you feel that way I\'ll shut up. ... Your choice."; + phrases[1][0] = "bye"; + phrases[1][1] = "Well, let\'s end our talk for now. See you later. Bye."; + return phrases; +} + +// The lower the index the higher the rank of the keyword (search is sequential). +// The index of the first keyword found in a user sentence maps to a respective +// reply ring as defined in `setupReplies()´. +// function setupKeywords(): array of KeyMapEntry +// C++ may not permit to return arrays like this - find an other way to pass the result! +// TODO Revise the return type and declare the parameters! +KeyMapEntry[] setupKeywords() +{ + // TODO: Check and accomplish variable declarations: + // The empty key string (last entry) is the default clause - will always be found + KeyMapEntry keywords[]; + + + // The empty key string (last entry) is the default clause - will always be found + keywords[39].keyword = ""; + keywords[39].index = 29; + keywords[0].keyword = "can you "; + keywords[0].index = 0; + keywords[1].keyword = "can i "; + keywords[1].index = 1; + keywords[2].keyword = "you are "; + keywords[2].index = 2; + keywords[3].keyword = "you\'re "; + keywords[3].index = 2; + keywords[4].keyword = "i don't "; + keywords[4].index = 3; + keywords[5].keyword = "i feel "; + keywords[5].index = 4; + keywords[6].keyword = "why don\'t you "; + keywords[6].index = 5; + keywords[7].keyword = "why can\'t i "; + keywords[7].index = 6; + keywords[8].keyword = "are you "; + keywords[8].index = 7; + keywords[9].keyword = "i can\'t "; + keywords[9].index = 8; + keywords[10].keyword = "i am "; + keywords[10].index = 9; + keywords[11].keyword = "i\'m "; + keywords[11].index = 9; + keywords[12].keyword = "you "; + keywords[12].index = 10; + keywords[13].keyword = "i want "; + keywords[13].index = 11; + keywords[14].keyword = "what "; + keywords[14].index = 12; + keywords[15].keyword = "how "; + keywords[15].index = 12; + keywords[16].keyword = "who "; + keywords[16].index = 12; + keywords[17].keyword = "where "; + keywords[17].index = 12; + keywords[18].keyword = "when "; + keywords[18].index = 12; + keywords[19].keyword = "why "; + keywords[19].index = 12; + keywords[20].keyword = "name "; + keywords[20].index = 13; + keywords[21].keyword = "cause "; + keywords[21].index = 14; + keywords[22].keyword = "sorry "; + keywords[22].index = 15; + keywords[23].keyword = "dream "; + keywords[23].index = 16; + keywords[24].keyword = "hello "; + keywords[24].index = 17; + keywords[25].keyword = "hi "; + keywords[25].index = 17; + keywords[26].keyword = "maybe "; + keywords[26].index = 18; + keywords[27].keyword = " no"; + keywords[27].index = 19; + keywords[28].keyword = "your "; + keywords[28].index = 20; + keywords[29].keyword = "always "; + keywords[29].index = 21; + keywords[30].keyword = "think "; + keywords[30].index = 22; + keywords[31].keyword = "alike "; + keywords[31].index = 23; + keywords[32].keyword = "yes "; + keywords[32].index = 24; + keywords[33].keyword = "friend "; + keywords[33].index = 25; + keywords[34].keyword = "computer"; + keywords[34].index = 26; + keywords[35].keyword = "bot "; + keywords[35].index = 26; + keywords[36].keyword = "smartphone"; + keywords[36].index = 27; + keywords[37].keyword = "father "; + keywords[37].index = 28; + keywords[38].keyword = "mother "; + keywords[38].index = 28; + return keywords; +} + +// Returns an array of pairs of mutualy substitutable +// function setupReflexions(): array of array[0..1] of string +// C++ may not permit to return arrays like this - find an other way to pass the result! +// TODO Revise the return type and declare the parameters! +string[][2] setupReflexions() +{ + // TODO: Check and accomplish variable declarations: + string reflexions[][2]; + + + reflexions[0][0] = " are "; + reflexions[0][1] = " am "; + reflexions[1][0] = " were "; + reflexions[1][1] = " was "; + reflexions[2][0] = " you "; + reflexions[2][1] = " I "; + reflexions[3][0] = " your"; + reflexions[3][1] = " my"; + reflexions[4][0] = " i\'ve "; + reflexions[4][1] = " you\'ve "; + reflexions[5][0] = " i\'m "; + reflexions[5][1] = " you\'re "; + reflexions[6][0] = " me "; + reflexions[6][1] = " you "; + reflexions[7][0] = " my "; + reflexions[7][1] = " your "; + reflexions[8][0] = " i "; + reflexions[8][1] = " you "; + reflexions[9][0] = " am "; + reflexions[9][1] = " are "; + return reflexions; +} + +// This routine sets up the reply rings addressed by the key words defined in +// routine `setupKeywords()´ and mapped hitherto by the cross table defined +// in `setupMapping()´ +// function setupReplies(): array of array of string +// C++ may not permit to return arrays like this - find an other way to pass the result! +// TODO Revise the return type and declare the parameters! +string[][/*???*/] setupReplies() +{ + // TODO: Check and accomplish variable declarations: + string setupReplies[][/*???*/]; + + + string replies[][/*???*/]; + replies[29][0] = "Say, do you have any psychological problems?"; + replies[29][1] = "What does that suggest to you?"; + replies[29][2] = "I see."; + replies[29][3] = "I'm not sure I understand you fully."; + replies[29][4] = "Come come elucidate your thoughts."; + replies[29][5] = "Can you elaborate on that?"; + replies[29][6] = "That is quite interesting."; + replies[0][0] = "Don't you believe that I can*?"; + replies[0][1] = "Perhaps you would like to be like me?"; + replies[0][2] = "You want me to be able to*?"; + replies[1][0] = "Perhaps you don't want to*?"; + replies[1][1] = "Do you want to be able to*?"; + replies[2][0] = "What makes you think I am*?"; + replies[2][1] = "Does it please you to believe I am*?"; + replies[2][2] = "Perhaps you would like to be*?"; + replies[2][3] = "Do you sometimes wish you were*?"; + replies[3][0] = "Don't you really*?"; + replies[3][1] = "Why don't you*?"; + replies[3][2] = "Do you wish to be able to*?"; + replies[3][3] = "Does that trouble you*?"; + replies[4][0] = "Do you often feel*?"; + replies[4][1] = "Are you afraid of feeling*?"; + replies[4][2] = "Do you enjoy feeling*?"; + replies[5][0] = "Do you really believe I don't*?"; + replies[5][1] = "Perhaps in good time I will*."; + replies[5][2] = "Do you want me to*?"; + replies[6][0] = "Do you think you should be able to*?"; + replies[6][1] = "Why can't you*?"; + replies[7][0] = "Why are you interested in whether or not I am*?"; + replies[7][1] = "Would you prefer if I were not*?"; + replies[7][2] = "Perhaps in your fantasies I am*?"; + replies[8][0] = "How do you know you can't*?"; + replies[8][1] = "Have you tried?"; + replies[8][2] = "Perhaps you can now*."; + replies[9][0] = "Did you come to me because you are*?"; + replies[9][1] = "How long have you been*?"; + replies[9][2] = "Do you believe it is normal to be*?"; + replies[9][3] = "Do you enjoy being*?"; + replies[10][0] = "We were discussing you--not me."; + replies[10][1] = "Oh, I*."; + replies[10][2] = "You're not really talking about me, are you?"; + replies[11][0] = "What would it mean to you if you got*?"; + replies[11][1] = "Why do you want*?"; + replies[11][2] = "Suppose you soon got*..."; + replies[11][3] = "What if you never got*?"; + replies[11][4] = "I sometimes also want*."; + replies[12][0] = "Why do you ask?"; + replies[12][1] = "Does that question interest you?"; + replies[12][2] = "What answer would please you the most?"; + replies[12][3] = "What do you think?"; + replies[12][4] = "Are such questions on your mind often?"; + replies[12][5] = "What is it that you really want to know?"; + replies[12][6] = "Have you asked anyone else?"; + replies[12][7] = "Have you asked such questions before?"; + replies[12][8] = "What else comes to mind when you ask that?"; + replies[13][0] = "Names don't interest me."; + replies[13][1] = "I don't care about names -- please go on."; + replies[14][0] = "Is that the real reason?"; + replies[14][1] = "Don't any other reasons come to mind?"; + replies[14][2] = "Does that reason explain anything else?"; + replies[14][3] = "What other reasons might there be?"; + replies[15][0] = "Please don't apologize!"; + replies[15][1] = "Apologies are not necessary."; + replies[15][2] = "What feelings do you have when you apologize?"; + replies[15][3] = "Don't be so defensive!"; + replies[16][0] = "What does that dream suggest to you?"; + replies[16][1] = "Do you dream often?"; + replies[16][2] = "What persons appear in your dreams?"; + replies[16][3] = "Are you disturbed by your dreams?"; + replies[17][0] = "How do you do ...please state your problem."; + replies[18][0] = "You don't seem quite certain."; + replies[18][1] = "Why the uncertain tone?"; + replies[18][2] = "Can't you be more positive?"; + replies[18][3] = "You aren't sure?"; + replies[18][4] = "Don't you know?"; + replies[19][0] = "Are you saying no just to be negative?"; + replies[19][1] = "You are being a bit negative."; + replies[19][2] = "Why not?"; + replies[19][3] = "Are you sure?"; + replies[19][4] = "Why no?"; + replies[20][0] = "Why are you concerned about my*?"; + replies[20][1] = "What about your own*?"; + replies[21][0] = "Can you think of a specific example?"; + replies[21][1] = "When?"; + replies[21][2] = "What are you thinking of?"; + replies[21][3] = "Really, always?"; + replies[22][0] = "Do you really think so?"; + replies[22][1] = "But you are not sure you*?"; + replies[22][2] = "Do you doubt you*?"; + replies[23][0] = "In what way?"; + replies[23][1] = "What resemblance do you see?"; + replies[23][2] = "What does the similarity suggest to you?"; + replies[23][3] = "What other connections do you see?"; + replies[23][4] = "Could there really be some connection?"; + replies[23][5] = "How?"; + replies[23][6] = "You seem quite positive."; + replies[24][0] = "Are you sure?"; + replies[24][1] = "I see."; + replies[24][2] = "I understand."; + replies[25][0] = "Why do you bring up the topic of friends?"; + replies[25][1] = "Do your friends worry you?"; + replies[25][2] = "Do your friends pick on you?"; + replies[25][3] = "Are you sure you have any friends?"; + replies[25][4] = "Do you impose on your friends?"; + replies[25][5] = "Perhaps your love for friends worries you."; + replies[26][0] = "Do computers worry you?"; + replies[26][1] = "Are you talking about me in particular?"; + replies[26][2] = "Are you frightened by machines?"; + replies[26][3] = "Why do you mention computers?"; + replies[26][4] = "What do you think machines have to do with your problem?"; + replies[26][5] = "Don't you think computers can help people?"; + replies[26][6] = "What is it about machines that worries you?"; + replies[27][0] = "Do you sometimes feel uneasy without a smartphone?"; + replies[27][1] = "Have you had these phantasies before?"; + replies[27][2] = "Does the world seem more real for you via apps?"; + replies[28][0] = "Tell me more about your family."; + replies[28][1] = "Who else in your family*?"; + replies[28][2] = "What does family relations mean for you?"; + replies[28][3] = "Come on, How old are you?"; + setupReplies = replies; + + return setupReplies; +} + +// Concept and lisp implementation published by Joseph Weizenbaum (MIT): +// "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +// Computational Linguistis 1(1966)9, pp. 36-45 +// Revision history: +// 2016-10-06 Initial version +// 2017-03-29 Two diagrams updated (comments translated to English) +// 2017-03-29 More keywords and replies added +// 2019-03-14 Replies and mapping reorganised for easier maintenance +// 2019-03-15 key map joined from keyword array and index map +// 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +// 2019-11-28 New global type "History" (to ensure a homogenous array) +// program ELIZA +int main(void) +{ + // BEGIN initialization for "History" + // END initialization for "History" + // BEGIN initialization for "KeyMapEntry" + // END initialization for "KeyMapEntry" + + // TODO: Check and accomplish variable declarations: + string varPart; + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + string userInput; + string reply; + int posAster; + int offsets[]; + bool isRepeated; + bool isGone; + int findInfo[2]; + + + // Title information + std::cout << "************* ELIZA **************" << std::endl; + std::cout << "* Original design by J. Weizenbaum" << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "* Adapted for Basic on IBM PC by" << std::endl; + std::cout << "* - Patricia Danielson" << std::endl; + std::cout << "* - Paul Hashfield" << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "* Adapted for Structorizer by" << std::endl; + std::cout << "* - Kay Gürtzig / FH Erfurt 2016" << std::endl; + std::cout << "* Version: 2.3 (2019-11-28)" << std::endl; + std::cout << "* (Requires at least Structorizer 3.30-03 to run)" << std::endl; + std::cout << "**********************************" << std::endl; + // Stores the last five inputs of the user in a ring buffer, + // the second component is the rolling (over-)write index. + History history = {{"", "", "", "", ""}, 0}; + const string replies[][/*???*/] = setupReplies(); + const string reflexions[][2] = setupReflexions(); + const string byePhrases[][2] = setupGoodByePhrases(); + const KeyMapEntry keyMap[] = setupKeywords(); + offsets[length(keyMap)-1] = 0; + isGone = false; + // Starter + std::cout << "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?" << std::endl; + do { + std::cin >> userInput; + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + userInput = normalizeInput(userInput); + isGone = checkGoodBye(userInput, byePhrases); + if (! isGone) { + reply = "Please don\'t repeat yourself!"; + isRepeated = checkRepetition(history, userInput); + if (! isRepeated) { + findInfo = findKeyword(keyMap, userInput); + ??? keyIndex = findInfo[0]; + if (keyIndex < 0) { + // Should never happen... + keyIndex = length(keyMap)-1; + } + KeyMapEntry entry = keyMap[keyIndex]; + // Variable part of the reply + varPart = ""; + if (length(entry.keyword) > 0) { + varPart = conjugateStrings(userInput, entry.keyword, findInfo[1], reflexions); + } + ??? replyRing = replies[entry.index]; + reply = replyRing[offsets[keyIndex]]; + offsets[keyIndex] = (offsets[keyIndex] + 1) % length(replyRing); + posAster = pos("*", reply); + if (posAster > 0) { + if (varPart == " ") { + reply = "You will have to elaborate more for me to help you."; + } + else { + delete(reply, posAster, 1); + insert(varPart, reply, posAster); + } + } + reply = adjustSpelling(reply); + } + std::cout << reply << std::endl; + } + } while (!(isGone)); + + return 0; +} diff --git a/samples/export/C++/SORTING_TEST_MAIN.cpp b/samples/export/C++/SORTING_TEST_MAIN.cpp index c2878a88..a7b3e340 100644 --- a/samples/export/C++/SORTING_TEST_MAIN.cpp +++ b/samples/export/C++/SORTING_TEST_MAIN.cpp @@ -1,4 +1,4 @@ -// Generated by Structorizer 3.30-02 +// Generated by Structorizer 3.30-03 // // Copyright (C) 2019-10-02 Kay Gürtzig // License: GPLv3-link @@ -18,17 +18,17 @@ // subrange. // function bubbleSort(values) // TODO Revise the return type and declare the parameters! -void bubbleSort(/*type?*/ values) +void bubbleSort(??? values) { // TODO: Check and accomplish variable declarations: - ende = length(values) - 2; + ??? ende = length(values) - 2; do { // The index of the most recent swapping (-1 means no swapping done). - posSwapped = -1; + ??? posSwapped = -1; for (int i = 0; i <= ende; i += (1)) { if (values[i] > values[i+1]) { - temp = values[i]; + ??? temp = values[i]; values[i] = values[i+1]; values[i+1] = temp; posSwapped = i; @@ -44,15 +44,15 @@ void bubbleSort(/*type?*/ values) // again. // function maxHeapify(heap, i, range) // TODO Revise the return type and declare the parameters! -void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) +void maxHeapify(??? heap, ??? i, ??? range) { // TODO: Check and accomplish variable declarations: // Indices of left and right child of node i - right = (i+1) * 2; - left = right - 1; + ??? right = (i+1) * 2; + ??? left = right - 1; // Index of the (local) maximum - max = i; + ??? max = i; if (left < range && heap[left] > heap[i]) { max = left; } @@ -60,7 +60,7 @@ void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) max = right; } if (max != i) { - temp = heap[i]; + ??? temp = heap[i]; heap[i] = heap[max]; heap[max] = temp; maxHeapify(heap, max, range); @@ -77,11 +77,11 @@ void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) // might still be avoided) but it is pretty clear. // function partition(values, start, stop, p): int // TODO Revise the return type and declare the parameters! -int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /*type?*/ p) +int partition(??? values, ??? start, ??? stop, ??? p) { // TODO: Check and accomplish variable declarations: - pivot = values[p]; + ??? pivot = values[p]; // Tausche das Pivot-Element an den start values[p] = values[start]; values[start] = pivot; @@ -91,7 +91,7 @@ int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /*type?*/ p) stop = stop - 1; // Still unseen elements? while (stop >= start) { - seen = values[start]; + ??? seen = values[start]; if (values[start] <= pivot) { // Swap pivot element with start element values[p] = seen; @@ -112,7 +112,7 @@ int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /*type?*/ p) // Checks whether or not the passed-in array is (ascendingly) sorted. // function testSorted(numbers): bool // TODO Revise the return type and declare the parameters! -bool testSorted(/*type?*/ numbers) +bool testSorted(??? numbers) { // TODO: Check and accomplish variable declarations: bool isSorted; @@ -140,7 +140,7 @@ bool testSorted(/*type?*/ numbers) // the root. // function buildMaxHeap(heap) // TODO Revise the return type and declare the parameters! -int buildMaxHeap(/*type?*/ heap) +int buildMaxHeap(??? heap) { // TODO: Check and accomplish variable declarations: int lgth; @@ -159,19 +159,19 @@ int buildMaxHeap(/*type?*/ heap) // stop is the index BEHIND the subsequence to be sorted. // function quickSort(values, start, stop) // TODO Revise the return type and declare the parameters! -int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) +int quickSort(??? values, ??? start, ??? stop) { - class ThrFunc3dfab37d_0{ + class ThrFunc7fed1521_0{ public: - void operator()(/*type?*/& values, /*type?*/& start, /*type?*/& p) { + void operator()(???& values, ???& start, ???& p) { // Sort left (lower) array part quickSort(values, start, p); } }; - class ThrFunc3dfab37d_1{ + class ThrFunc7fed1521_1{ public: - void operator()(/*type?*/& values, /*type?*/& p, /*type?*/& stop) { + void operator()(???& values, ???& p, ???& stop) { // Sort right (higher) array part quickSort(values, p+1, stop); } @@ -183,7 +183,7 @@ int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) if (stop >= start + 2) { // Select a pivot element, be p its index. // (here: randomly chosen element out of start ... stop-1) - p = random(stop-start) + start; + ??? p = random(stop-start) + start; // Partition the array into smaller and greater elements // Get the resulting (and final) position of the pivot element // Partition the array into smaller and greater elements @@ -193,14 +193,14 @@ int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) // Parallel section { - ThrFunc3dfab37d_0 thrfunc3dfab37d_0; - std::thread thr3dfab37d_0(thrfunc3dfab37d_0, values, start, p); + ThrFunc7fed1521_0 thrfunc7fed1521_0; + std::thread thr7fed1521_0(thrfunc7fed1521_0, values, start, p); - ThrFunc3dfab37d_1 thrfunc3dfab37d_1; - std::thread thr3dfab37d_1(thrfunc3dfab37d_1, values, p, stop); + ThrFunc7fed1521_1 thrfunc7fed1521_1; + std::thread thr7fed1521_1(thrfunc7fed1521_1, values, p, stop); - thr3dfab37d_0.join(); - thr3dfab37d_1.join(); + thr7fed1521_0.join(); + thr7fed1521_1.join(); } } @@ -212,7 +212,7 @@ int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) // algorithm // function heapSort(values) // TODO Revise the return type and declare the parameters! -int heapSort(/*type?*/ values) +int heapSort(??? values) { // TODO: Check and accomplish variable declarations: int heapRange; @@ -223,7 +223,7 @@ int heapSort(/*type?*/ values) for (int k = heapRange - 1; k >= 1; k += (-1)) { heapRange = heapRange - 1; // Swap the maximum value (root of the heap) to the heap end - maximum = values[0]; + ??? maximum = values[0]; values[0] = values[heapRange]; values[heapRange] = maximum; maxHeapify(values, 0, heapRange); @@ -239,32 +239,35 @@ int heapSort(/*type?*/ values) // program SORTING_TEST_MAIN int main(void) { - class ThrFunc4f085546_0{ + class ThrFunc247e34b9_0{ public: - void operator()(/*type?*/& values1) { + void operator()(int values1[]) { bubbleSort(values1); } }; - class ThrFunc4f085546_1{ + class ThrFunc247e34b9_1{ public: - void operator()(/*type?*/& values2, /*type?*/& elementCount) { + void operator()(??? values2[], ???& elementCount) { quickSort(values2, 0, elementCount); } }; - class ThrFunc4f085546_2{ + class ThrFunc247e34b9_2{ public: - void operator()(/*type?*/& values3) { + void operator()(??? values3[]) { heapSort(values3); } }; // TODO: Check and accomplish variable declarations: - ??? values3; - ??? values2; - ??? values1; + ??? values3[]; + ??? values2[]; + int values1[]; ??? show; + bool ok3; + bool ok2; + bool ok1; ??? modus; ??? elementCount; @@ -288,7 +291,7 @@ int main(void) break; } } - // Kopiere das Array für exakte Vergleichbarkeit + // Copy the array for exact comparability for (int i = 0; i <= elementCount-1; i += (1)) { values2[i] = values1[i]; values3[i] = values1[i]; @@ -296,18 +299,18 @@ int main(void) // Parallel section { - ThrFunc4f085546_0 thrfunc4f085546_0; - std::thread thr4f085546_0(thrfunc4f085546_0, values1); + ThrFunc247e34b9_0 thrfunc247e34b9_0; + std::thread thr247e34b9_0(thrfunc247e34b9_0, values1); - ThrFunc4f085546_1 thrfunc4f085546_1; - std::thread thr4f085546_1(thrfunc4f085546_1, values2, elementCount); + ThrFunc247e34b9_1 thrfunc247e34b9_1; + std::thread thr247e34b9_1(thrfunc247e34b9_1, values2, elementCount); - ThrFunc4f085546_2 thrfunc4f085546_2; - std::thread thr4f085546_2(thrfunc4f085546_2, values3); + ThrFunc247e34b9_2 thrfunc247e34b9_2; + std::thread thr247e34b9_2(thrfunc247e34b9_2, values3); - thr4f085546_0.join(); - thr4f085546_1.join(); - thr4f085546_2.join(); + thr247e34b9_0.join(); + thr247e34b9_1.join(); + thr247e34b9_2.join(); } ok1 = testSorted(values1); diff --git a/samples/export/C++/TextDemo.cpp b/samples/export/C++/TextDemo.cpp new file mode 100644 index 00000000..511870cb --- /dev/null +++ b/samples/export/C++/TextDemo.cpp @@ -0,0 +1,1215 @@ +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2019-10-10 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// +#include + + +// Draws a blank for font height h, ignoring the colorNo +// function blank(h, colorNo) +// TODO Revise the return type and declare the parameters! +void blank(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + penUp(); + right(90); + forward(width); // color = ffffff + left(90); +} + +// function forward(len, color) +// TODO Revise the return type and declare the parameters! +void forward(??? len, ??? color) +{ + // TODO: Check and accomplish variable declarations: + + switch (color) { + case 1: + forward(len); // color = ffffff + break; + case 2: + forward(len); // color = ff8080 + break; + case 3: + forward(len); // color = ffff80 + break; + case 4: + forward(len); // color = 80ff80 + break; + case 5: + forward(len); // color = 80ffff + break; + case 6: + forward(len); // color = 0080ff + break; + case 7: + forward(len); // color = ff80c0 + break; + case 8: + forward(len); // color = c0c0c0 + break; + case 9: + forward(len); // color = ff8000 + break; + case 10: + forward(len); // color = 8080ff + break; + } +} + +// Draws letter A in colour specified by colorNo with font height h +// from the current turtle position. +// function letterA(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterA(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(h*h + width*width/4.0); + rotAngle = toDegrees(atan(width/2.0/h)); + right(rotAngle); + forward(hypo/2.0, colorNo); + right(90 - rotAngle); + forward(width/2.0, colorNo); + penUp(); + backward(width/2.0); // color = ffffff + penDown(); + left(90 - rotAngle); + forward(hypo/2.0, colorNo); + left(2*rotAngle); + forward(-hypo, colorNo); + right(rotAngle); +} + +// Draws letter E in colour specified by colorNo with font height h +// from the current turtle position. +// function letterE(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterE(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); // color = ffffff + left(90); + penDown(); + forward(width, colorNo); + left(90); +} + +// Draws letter F in colour specified by colorNo with font height h +// from the current turtle position. +// function letterF(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterF(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); // color = ffffff + left(90); + forward(width); // color = ffffff + penDown(); + left(90); +} + +// Draws letter H in colour specified by colorNo with font height h +// from the current turtle position. +// function letterH(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterH(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + penUp(); + right(90); + forward(width); // color = ffffff + right(90); + penDown(); + forward(h/2.0, colorNo); + right(90); + forward(width, colorNo); + penUp(); + backward(width); // color = ffffff + left(90); + penDown(); + forward(h/2.0, colorNo); + left(180); +} + +// Draws letter I in colour specified by colorNo with font height h +// from the current turtle position. +// function letterI(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterI(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / sqrt(2.0); + penUp(); + right(90); + forward(c); // color = ffffff + penDown(); + forward(b, colorNo); + penUp(); + backward(b/2.0); // color = ffffff + left(90); + penDown(); + forward(h, colorNo); + penUp(); + right(90); + backward(b/2.0); // color = ffffff + penDown(); + forward(b, colorNo); + penUp(); + forward(b/2 + c); // color = ffffff + left(90); + backward(h); // color = ffffff + penDown(); +} + +// Draws letter K in colour specified by colorNo with font height h +// from the current turtle position. +// function letterK(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterK(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + ??? diag = h/sqrt(2.0); + forward(h, colorNo); + penUp(); + right(90); + forward(width); // color = ffffff + right(135); + penDown(); + forward(diag, colorNo); + left(90); + forward(diag, colorNo); + left(135); +} + +// Draws letter L in colour specified by colorNo with font height h +// from the current turtle position. +// function letterL(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterL(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + forward(h, colorNo); + penUp(); + backward(h); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); +} + +// Draws letter M in colour specified by colorNo with font height h +// from the current turtle position. +// function letterM(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterM(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + ??? width = h/2.0; + ??? hypo = sqrt(width*width + h*h)/2.0; + rotAngle = toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + left(rotAngle); + forward(-h, colorNo); +} + +// Draws letter N in colour specified by colorNo with font height h +// from the current turtle position. +// function letterN(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterN(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(rotAngle); + forward(h, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// Draws letter T in colour specified by colorNo with font height h +// from the current turtle position. +// function letterT(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterT(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + penUp(); + forward(h); // color = ffffff + penDown(); + right(90); + forward(width, colorNo); + penUp(); + backward(width/2.0); // color = ffffff + penDown(); + right(90); + forward(h, colorNo); + left(90); + penUp(); + forward(width/2.0); // color = ffffff + penDown(); + left(90); +} + +// Draws letter V in colour specified by colorNo with font height h +// from the current turtle position. +// function letterV(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterV(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(h*h + width*width/4.0); + rotAngle = toDegrees(atan(width/2.0/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); // color = ffffff + penDown(); +} + +// Draws letter W in colour specified by colorNo with font height h +// from the current turtle position. +// function letterW(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterW(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + ??? width_3 = width/3.0; + hypo = sqrt(width_3*width_3 + h*h); + rotAngle = toDegrees(atan(width_3/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width_3); // color = ffffff + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); // color = ffffff + penDown(); +} + +// Draws letter X in colour specified by colorNo with font height h +// from the current turtle position. +// function letterX(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterX(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + right(rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width); // color = ffffff + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); +} + +// Draws letter Y in colour specified by colorNo with font height h +// from the current turtle position. +// function letterY(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterY(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + ??? width = h/2.0; + ??? hypo = sqrt(width*width + h*h)/2.0; + rotAngle = toDegrees(atan(width/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); + penUp(); + backward(h/2.0); // color = ffffff + penDown(); + forward(h/2.0, colorNo); + right(rotAngle); + forward(hypo, colorNo); + left(rotAngle); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// Draws letter Z in colour specified by colorNo with font height h +// from the current turtle position. +// function letterZ(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterZ(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + penUp(); + forward(h); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90-rotAngle); + forward(-hypo, colorNo); + right(90-rotAngle); + forward(width, colorNo); + left(90); +} + +// Draws nEdges edges of a regular n-polygon with edge length a +// counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +// function polygonPart(a: double; n: integer; ctrclkws: boolean; nEdges: integer; color: int) +// TODO Revise the return type and declare the parameters! +void polygonPart(double a, int n, bool ctrclkws, int nEdges, int color) +{ + // TODO: Check and accomplish variable declarations: + + ??? rotAngle = 360.0/n; + if (ctrclkws) { + rotAngle = -rotAngle; + } + for (int k = 1; k <= nEdges; k += (1)) { + right(rotAngle); + forward(a, color); + } +} + +// Draws a dummy character (small centered square) with font height h and +// the colour encoded by colorNo +// function charDummy(h, colorNo) +// TODO Revise the return type and declare the parameters! +void charDummy(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + ??? width = h / 2.0; + // Octagon edge length (here: edge lengzh of the square) + ??? b = width / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = (width - b) / 2.0; + ??? d = b / sqrt(2.0); + penUp(); + forward(h/2.0-b/2.0); // color = ffffff + right(90); + forward(c); // color = ffffff + right(90); + penDown(); + // Draws the square with edge length b + polygonPart(b, 4, true, 4, colorNo); + penUp(); + left(90); + forward(b + c); // color = ffffff + left(90); + backward(h/2.0-b/2.0); // color = ffffff + penDown(); +} + +// Draws a comma in colour specified by colorNo with font height h +// from the current turtle position. +// function comma(h, colorNo) +// TODO Revise the return type and declare the parameters! +void comma(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + rotAngle = toDegrees(atan(0.5)); + ??? hypo = c * sqrt(1.25); + penUp(); + right(90); + forward((c+b)/2.0 + c); // color = ffffff + penDown(); + // Counterclockwise draw 3 edges of a square with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 3, colorNo); + left(90); + forward(c/2.0, colorNo); + right(90); + forward(c, colorNo); + left(180 - rotAngle); + forward(hypo, colorNo); + penUp(); + right(90 - rotAngle); + forward((c + b)/2.0); // color = ffffff + left(90); + penDown(); +} + +// Draws an exclamation mark in the colour encoded by colorNo with font height h +// from the current turtle position. +// function exclMk(h, colorNo) +// TODO Revise the return type and declare the parameters! +void exclMk(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle2; + // 360°/8 + int rotAngle; + double hypo; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + ??? width = h/2.0; + ??? length1 = h - (b+c)/2.0; + ??? length2 = length1 - 2*c; + hypo = sqrt(width*width/16.0 + length2*length2); + // 360°/8 + rotAngle = 45; + rotAngle2 = toDegrees(atan(width/4.0/length2)); + penUp(); + forward(length1); // color = ffffff + right(90); + forward(width/2.0); // color = ffffff + left(90 + rotAngle); + penDown(); + // Clockwise draw 5 edges of an octagon with edge length b/2 + // in the colour endcoded by colorNo + polygonPart(b/2.0, 8, false, 5, colorNo); + right(rotAngle2); + forward(hypo, colorNo); + left(2*rotAngle2); + forward(-hypo, colorNo); + penUp(); + forward(hypo); // color = ffffff + right(rotAngle2); + forward(c); // color = ffffff + left(90); + forward(c/2.0); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + backward(c); // color = ffffff + penDown(); +} + +// Draws a full stop in colour specified by colorNo with font height h +// from the current turtle position. +// function fullSt(h, colorNo) +// TODO Revise the return type and declare the parameters! +void fullSt(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + penUp(); + right(90); + forward((c+b)/2.0 + c); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + penDown(); +} + +// Draws letter B in colour specified by colorNo with font height h +// from the current turtle position. +// function letterB(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterB(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the outer corner triangle of the octagon + ??? c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + c); // color = ffffff + penDown(); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); +} + +// Draws letter C in the colour encoded by colorNo with font height h +// from the current turtle position. +// function letterC(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterC(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the outer trinagle at the octagon corner + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Clockwise draws 3 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + penUp(); + forward(2*b + 2*c); // color = ffffff + penDown(); + // Counterclockwise draws 4 edges of an octagon with edge length b + // iin the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); +} + +// Draws letter D in colour specified by colorNo with font height h +// from the current turtle position. +// function letterD(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterD(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + forward(b + 2*c, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); +} + +// Draws letter G in colour specified by colorNo with font height h +// from the current turtle position. +// function letterG(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterG(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon. + ??? c = b / sqrt(2.0); + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(c, colorNo); + left(90); + forward(b/2.0 + c, colorNo); + penUp(); + backward(b/2.0 + c); // color = ffffff + right(90); + forward(b + c); // color = ffffff + penDown(); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); +} + +// Draws letter J in colour encoded by colorNo with font height h +// from the current turtle position. +// function letterJ(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterJ(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 3 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// Draws letter O in colour specified by colorNo with font height h +// from the current turtle position. +// function letterO(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterO(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / sqrt(2.0); + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); +} + +// Draws letter P in colour specified by colorNo with font height h +// from the current turtle position. +// function letterP(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterP(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + backward(b + 2*c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + penDown(); + left(180); +} + +// Draws letter Q in colour specified by colorNo with font height h +// from the current turtle position. +// function letterQ(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterQ(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + right(rotAngle); + backward(b); // color = ffffff + penDown(); + forward(b, colorNo); + left(90 + rotAngle); +} + +// Zeichnet den Buchstaben R von der Turtleposition aus +// mit Zeilenhöhe h +// function letterR(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterR(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + left(90 + rotAngle); + forward(sqrt(2.0)*(b + 2*c), colorNo); + left(90 + rotAngle); +} + +// Draws letter S in colour specified by colorNo with font height h +// from the current turtle position. +// function letterS(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterS(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 6 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 6, colorNo); + // Clockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + right(rotAngle); + penUp(); + forward(2*b + 3*c); // color = ffffff + penDown(); + left(180); +} + +// Draws letter U in colour specified by colorNo with font height h +// from the current turtle position. +// function letterU(h, colorNo) +// TODO Revise the return type and declare the parameters! +void letterU(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // edge length of a regular octagon + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + forward(h - c, colorNo); + penUp(); + backward(h-c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// Draws a question mark in colour specified by colorNo with font height h +// from the current turtle position. +// function qstnMk(h, colorNo) +// TODO Revise the return type and declare the parameters! +void qstnMk(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(h-c); // color = ffffff + penDown(); + // Counterclockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + forward(c, colorNo); + left(rotAngle); + forward(b/2.0, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(c/2.0); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + backward(c); // color = ffffff + penDown(); +} + +// Has the turtle draw the given string 'text´ with font height 'h´ (in +// pixels) and the colour coded by integer 'c´ from the current Turtle +// position to the Turtle canvas. If the turtle looks North then +// the text will be written rightwards. In the event, the turtle will be +// placed behind the text in original orientation (such that the next text +// would be written like a continuation. Colour codes: +// 1 = black +// 2 = red +// 3 = yellow +// 4 = green +// 5 = cyan +// 6 = blue +// 7 = pink +// 8 = grey +// 9 = orange +// 10 = violet +// All letters (ASCII) will be converted to uppercase, digits cannot +// be represented, the set of representable special characters is: +// '.', ',', '!', '?'. Other characters will be shown as a small +// centred square (dummy character). +// function drawText(text: string; h: integer; c: integer) +// TODO Revise the return type and declare the parameters! +void drawText(string text, int h, int c) +{ + // TODO: Check and accomplish variable declarations: + string letter; + + + ??? gap = h/10.0; + for (int k = 1; k <= length(text); k += (1)) { + letter = uppercase(copy(text, k, 1)); + if (letter == ",") { + comma(h,c); + } + else { + // "," cannot be chacked against because the comma is misinterpreted + // as selector list separator. + switch (letter) { + case "A": + letterA(h,c); + break; + case "B": + letterB(h,c); + break; + case "C": + letterC(h,c); + break; + case "D": + letterD(h,c); + break; + case "E": + letterE(h,c); + break; + case "F": + letterF(h,c); + break; + case "G": + letterG(h,c); + break; + case "H": + letterH(h,c); + break; + case "I": + letterI(h,c); + break; + case "J": + letterJ(h,c); + break; + case "K": + letterK(h,c); + break; + case "L": + letterL(h,c); + break; + case "M": + letterM(h,c); + break; + case "N": + letterN(h,c); + break; + case "O": + letterO(h,c); + break; + case "P": + letterP(h,c); + break; + case "Q": + letterQ(h,c); + break; + case "R": + letterR(h,c); + break; + case "S": + letterS(h,c); + break; + case "T": + letterT(h,c); + break; + case "U": + letterU(h,c); + break; + case "V": + letterV(h,c); + break; + case "W": + letterW(h,c); + break; + case "X": + letterX(h,c); + break; + case "Y": + letterY(h,c); + break; + case "Z": + letterZ(h,c); + break; + case " ": + blank(h,c); + break; + case "!": + exclMk(h,c); + break; + case "?": + qstnMk(h,c); + break; + case ".": + fullSt(h,c); + break; + default: + charDummy(h,c); + } + } + right(90); + penUp(); + forward(gap); // color = ffffff + penDown(); + left(90); + } +} + +// Demo program for routine drawText() +// Asks the user to enter a text, a wanted text height and colour, +// and then draws this string onto the turtle screen. Places every +// entered text to a new line. +// program TextDemo +int main(void) +{ + // TODO: Check and accomplish variable declarations: + int y; + ??? height; + ??? colour; + + + std::cout << "This is a demo program for text writing with Turleizer." << std::endl; + showTurtle(); + penDown(); + y = 0; + do { + std::cout << "Enter some text (empty string to exit)"; std::cin >> text; + // Make sure the content is interpreted as string + ??? text = "" + text; + if (text != "") { + do { + std::cout << "Height of the text (pixels)"; std::cin >> height; + } while (!(height >= 5)); + do { + std::cout << "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"; std::cin >> colour; + } while (!(colour >= 1 && colour <= 10)); + y = y + height + 2; + gotoXY(0, y - 2); + drawText(text, height, colour); + } + } while (!(text == "")); + gotoXY(0, y + 15); + drawText("Thank you, bye.", 10, 4); + hideTurtle(); + + return 0; +} diff --git a/samples/export/C/ELIZA_2.3.c b/samples/export/C/ELIZA_2.3.c new file mode 100644 index 00000000..370e87bd --- /dev/null +++ b/samples/export/C/ELIZA_2.3.c @@ -0,0 +1,640 @@ +// program ELIZA +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2018-05-14 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// + +#define _CRT_SECURE_NO_WARNINGS +#include +#include + +#include + + +// histArray contains the most recent user replies as ring buffer; +// histIndex is the index where the next reply is to be stored (= index of the oldest +// cached user reply). +// Note: The depth of the history is to be specified by initializing a variable of this type, +// e.g. for a history of depth 5: +// myhistory <- History{{"", "", "", "", ""}, 0} +struct History { + char*[] histArray; + int histIndex; +}; + +// Associates a key word in the text with an index in the reply ring array +struct KeyMapEntry { + char* keyword; + int index; +}; + + +// function adjustSpelling(sentence: string): string +// Cares for correct letter case among others +// TODO: Revise the return type and declare the parameters. +char* adjustSpelling(char* sentence) +{ + // TODO: Check and accomplish variable declarations: + char* word; + char* start; + char* result; + int position; + + + result = sentence; + position = 1; + while ((position <= length(sentence)) && (copy(sentence, position, 1) == " ")) { + position = position + 1; + } + if (position <= length(sentence)) { + start = copy(sentence, 1, position); + delete(result, 1, position); + insert(uppercase(start), result, 1); + } + { + char* array324bf690[2] = {" i ", " i\'"}; + int index324bf690; + for (index324bf690 = 0; index324bf690 < 2; index324bf690++) { + char* word = array324bf690[index324bf690]; + position = pos(word, result); + while (position > 0) { + delete(result, position+1, 1); + insert("I", result, position+1); + position = pos(word, result); + } + } + } + + return result; +} + +// function checkGoodBye(text: string; phrases: array of array[0..1] of string): boolean +// Checks whether the given text contains some kind of +// good-bye phrase inducing the end of the conversation +// and if so writes a correspding good-bye message and +// returns true, otherwise false +// TODO: Revise the return type and declare the parameters. +bool checkGoodBye(char* text, char* phrases[][2]) +{ + // TODO: Check and accomplish variable declarations: + bool saidBye; + char* pair[]; + + + // TODO: + // For any output using the 'printf' function you need to fill the first argument: + // http://en.wikipedia.org/wiki/Printf#printf_format_placeholders + + { + // TODO: Find out and fill in the number of elements of the array phrases here! + int count14015767 = ???; + int index14015767; + for (index14015767 = 0; index14015767 < count14015767; index14015767++) { + char* pair[] = phrases[index14015767]; + if (pos(pair[0], text) > 0) { + saidBye = true; + printf("TODO: specify format\n", pair[1]); + return true; + } + } + } + return false; +} + +// function checkRepetition(history: History; newInput: string): boolean +// Checks whether newInput has occurred among the recently cached +// input strings in the histArray component of history and updates the history. +// TODO: Revise the return type and declare the parameters. +bool checkRepetition(struct History history, char* newInput) +{ + // TODO: Check and accomplish variable declarations: + int i; + int histDepth; + bool hasOccurred; + + + hasOccurred = false; + if (length(newInput) > 4) { + histDepth = length(history.histArray); + for (i = 0; i <= histDepth-1; i += (1)) { + if (newInput == history.histArray[i]) { + hasOccurred = true; + } + } + history.histArray[history.histIndex] = newInput; + history.histIndex = (history.histIndex + 1) % (histDepth); + } + return hasOccurred; +} + +// function conjugateStrings(sentence: string; key: string; keyPos: integer; flexions: array of array[0..1] of string): string +// TODO: Revise the return type and declare the parameters. +char* conjugateStrings(char* sentence, char* key, int keyPos, char* flexions[][2]) +{ + // TODO: Check and accomplish variable declarations: + char* right; + char* result; + int position; + char* pair[]; + char* left; + + + result = " " + copy(sentence, keyPos + length(key), length(sentence)) + " "; + { + // TODO: Find out and fill in the number of elements of the array flexions here! + int count6e7cbe69 = ???; + int index6e7cbe69; + for (index6e7cbe69 = 0; index6e7cbe69 < count6e7cbe69; index6e7cbe69++) { + char* pair[] = flexions[index6e7cbe69]; + left = ""; + right = result; + position = pos(pair[0], right); + while (position > 0) { + left = left + copy(right, 1, position-1) + pair[1]; + right = copy(right, position + length(pair[0]), length(right)); + position = pos(pair[0], right); + } + result = left + right; + } + } + // Eliminate multiple spaces + position = pos(" ", result); + while (position > 0) { + result = copy(result, 1, position-1) + copy(result, position+1, length(result)); + position = pos(" ", result); + } + + return result; +} + +// function findKeyword(const keyMap: array of KeyMapEntry; sentence: string): array[0..1] of integer +// Looks for the occurrence of the first of the strings +// contained in keywords within the given sentence (in +// array order). +// Returns an array of +// 0: the index of the first identified keyword (if any, otherwise -1), +// 1: the position inside sentence (0 if not found) +// TODO: Revise the return type and declare the parameters. +// C does not permit to return arrays - find an other way to pass the result! +int[2] findKeyword(const array of KeyMapEntry keyMap, char* sentence) +{ + // TODO: Check and accomplish variable declarations: + const array of KeyMapEntry keyMap; + int result[2]; + int position; + int i; + struct KeyMapEntry entry; + + + result[0] = -1; + result[1] = 0; + i = 0; + while ((result[0] < 0) && (i < length(keyMap))) { + entry = keyMap[i]; + position = pos(entry.keyword, sentence); + if (position > 0) { + result[0] = i; + result[1] = position; + } + i = i+1; + } + + return result; +} + +// function normalizeInput(sentence: string): string +// Converts the sentence to lowercase, eliminates all +// interpunction (i.e. ',', '.', ';'), and pads the +// sentence among blanks +// TODO: Revise the return type and declare the parameters. +char* normalizeInput(char* sentence) +{ + // TODO: Check and accomplish variable declarations: + char symbol; + char* result; + int position; + + + sentence = lowercase(sentence); + { + char arrayb4f79f[5] = {'.', ',', ';', '!', '?'}; + int indexb4f79f; + for (indexb4f79f = 0; indexb4f79f < 5; indexb4f79f++) { + char symbol = arrayb4f79f[indexb4f79f]; + position = pos(symbol, sentence); + while (position > 0) { + sentence = copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)); + position = pos(symbol, sentence); + } + } + } + result = " " + sentence + " "; + + return result; +} + +// function setupGoodByePhrases(): array of array[0..1] of string +// TODO: Revise the return type and declare the parameters. +// C does not permit to return arrays - find an other way to pass the result! +char*[][2] setupGoodByePhrases() +{ + // TODO: Check and accomplish variable declarations: + char* phrases[][2]; + + + phrases[0][0] = " shut"; + phrases[0][1] = "Okay. If you feel that way I\'ll shut up. ... Your choice."; + phrases[1][0] = "bye"; + phrases[1][1] = "Well, let\'s end our talk for now. See you later. Bye."; + return phrases; +} + +// function setupKeywords(): array of KeyMapEntry +// The lower the index the higher the rank of the keyword (search is sequential). +// The index of the first keyword found in a user sentence maps to a respective +// reply ring as defined in `setupReplies()´. +// TODO: Revise the return type and declare the parameters. +// C does not permit to return arrays - find an other way to pass the result! +KeyMapEntry[] setupKeywords() +{ + // TODO: Check and accomplish variable declarations: + // The empty key string (last entry) is the default clause - will always be found + KeyMapEntry keywords[]; + + + // The empty key string (last entry) is the default clause - will always be found + keywords[39].keyword = ""; + keywords[39].index = 29; + keywords[0].keyword = "can you "; + keywords[0].index = 0; + keywords[1].keyword = "can i "; + keywords[1].index = 1; + keywords[2].keyword = "you are "; + keywords[2].index = 2; + keywords[3].keyword = "you\'re "; + keywords[3].index = 2; + keywords[4].keyword = "i don't "; + keywords[4].index = 3; + keywords[5].keyword = "i feel "; + keywords[5].index = 4; + keywords[6].keyword = "why don\'t you "; + keywords[6].index = 5; + keywords[7].keyword = "why can\'t i "; + keywords[7].index = 6; + keywords[8].keyword = "are you "; + keywords[8].index = 7; + keywords[9].keyword = "i can\'t "; + keywords[9].index = 8; + keywords[10].keyword = "i am "; + keywords[10].index = 9; + keywords[11].keyword = "i\'m "; + keywords[11].index = 9; + keywords[12].keyword = "you "; + keywords[12].index = 10; + keywords[13].keyword = "i want "; + keywords[13].index = 11; + keywords[14].keyword = "what "; + keywords[14].index = 12; + keywords[15].keyword = "how "; + keywords[15].index = 12; + keywords[16].keyword = "who "; + keywords[16].index = 12; + keywords[17].keyword = "where "; + keywords[17].index = 12; + keywords[18].keyword = "when "; + keywords[18].index = 12; + keywords[19].keyword = "why "; + keywords[19].index = 12; + keywords[20].keyword = "name "; + keywords[20].index = 13; + keywords[21].keyword = "cause "; + keywords[21].index = 14; + keywords[22].keyword = "sorry "; + keywords[22].index = 15; + keywords[23].keyword = "dream "; + keywords[23].index = 16; + keywords[24].keyword = "hello "; + keywords[24].index = 17; + keywords[25].keyword = "hi "; + keywords[25].index = 17; + keywords[26].keyword = "maybe "; + keywords[26].index = 18; + keywords[27].keyword = " no"; + keywords[27].index = 19; + keywords[28].keyword = "your "; + keywords[28].index = 20; + keywords[29].keyword = "always "; + keywords[29].index = 21; + keywords[30].keyword = "think "; + keywords[30].index = 22; + keywords[31].keyword = "alike "; + keywords[31].index = 23; + keywords[32].keyword = "yes "; + keywords[32].index = 24; + keywords[33].keyword = "friend "; + keywords[33].index = 25; + keywords[34].keyword = "computer"; + keywords[34].index = 26; + keywords[35].keyword = "bot "; + keywords[35].index = 26; + keywords[36].keyword = "smartphone"; + keywords[36].index = 27; + keywords[37].keyword = "father "; + keywords[37].index = 28; + keywords[38].keyword = "mother "; + keywords[38].index = 28; + return keywords; +} + +// function setupReflexions(): array of array[0..1] of string +// Returns an array of pairs of mutualy substitutable +// TODO: Revise the return type and declare the parameters. +// C does not permit to return arrays - find an other way to pass the result! +char*[][2] setupReflexions() +{ + // TODO: Check and accomplish variable declarations: + char* reflexions[][2]; + + + reflexions[0][0] = " are "; + reflexions[0][1] = " am "; + reflexions[1][0] = " were "; + reflexions[1][1] = " was "; + reflexions[2][0] = " you "; + reflexions[2][1] = " I "; + reflexions[3][0] = " your"; + reflexions[3][1] = " my"; + reflexions[4][0] = " i\'ve "; + reflexions[4][1] = " you\'ve "; + reflexions[5][0] = " i\'m "; + reflexions[5][1] = " you\'re "; + reflexions[6][0] = " me "; + reflexions[6][1] = " you "; + reflexions[7][0] = " my "; + reflexions[7][1] = " your "; + reflexions[8][0] = " i "; + reflexions[8][1] = " you "; + reflexions[9][0] = " am "; + reflexions[9][1] = " are "; + return reflexions; +} + +// function setupReplies(): array of array of string +// This routine sets up the reply rings addressed by the key words defined in +// routine `setupKeywords()´ and mapped hitherto by the cross table defined +// in `setupMapping()´ +// TODO: Revise the return type and declare the parameters. +// C does not permit to return arrays - find an other way to pass the result! +char*[][/*???*/] setupReplies() +{ + // TODO: Check and accomplish variable declarations: + char* setupReplies[][/*???*/]; + char* replies[][/*???*/]; + + + replies[29][0] = "Say, do you have any psychological problems?"; + replies[29][1] = "What does that suggest to you?"; + replies[29][2] = "I see."; + replies[29][3] = "I'm not sure I understand you fully."; + replies[29][4] = "Come come elucidate your thoughts."; + replies[29][5] = "Can you elaborate on that?"; + replies[29][6] = "That is quite interesting."; + replies[0][0] = "Don't you believe that I can*?"; + replies[0][1] = "Perhaps you would like to be like me?"; + replies[0][2] = "You want me to be able to*?"; + replies[1][0] = "Perhaps you don't want to*?"; + replies[1][1] = "Do you want to be able to*?"; + replies[2][0] = "What makes you think I am*?"; + replies[2][1] = "Does it please you to believe I am*?"; + replies[2][2] = "Perhaps you would like to be*?"; + replies[2][3] = "Do you sometimes wish you were*?"; + replies[3][0] = "Don't you really*?"; + replies[3][1] = "Why don't you*?"; + replies[3][2] = "Do you wish to be able to*?"; + replies[3][3] = "Does that trouble you*?"; + replies[4][0] = "Do you often feel*?"; + replies[4][1] = "Are you afraid of feeling*?"; + replies[4][2] = "Do you enjoy feeling*?"; + replies[5][0] = "Do you really believe I don't*?"; + replies[5][1] = "Perhaps in good time I will*."; + replies[5][2] = "Do you want me to*?"; + replies[6][0] = "Do you think you should be able to*?"; + replies[6][1] = "Why can't you*?"; + replies[7][0] = "Why are you interested in whether or not I am*?"; + replies[7][1] = "Would you prefer if I were not*?"; + replies[7][2] = "Perhaps in your fantasies I am*?"; + replies[8][0] = "How do you know you can't*?"; + replies[8][1] = "Have you tried?"; + replies[8][2] = "Perhaps you can now*."; + replies[9][0] = "Did you come to me because you are*?"; + replies[9][1] = "How long have you been*?"; + replies[9][2] = "Do you believe it is normal to be*?"; + replies[9][3] = "Do you enjoy being*?"; + replies[10][0] = "We were discussing you--not me."; + replies[10][1] = "Oh, I*."; + replies[10][2] = "You're not really talking about me, are you?"; + replies[11][0] = "What would it mean to you if you got*?"; + replies[11][1] = "Why do you want*?"; + replies[11][2] = "Suppose you soon got*..."; + replies[11][3] = "What if you never got*?"; + replies[11][4] = "I sometimes also want*."; + replies[12][0] = "Why do you ask?"; + replies[12][1] = "Does that question interest you?"; + replies[12][2] = "What answer would please you the most?"; + replies[12][3] = "What do you think?"; + replies[12][4] = "Are such questions on your mind often?"; + replies[12][5] = "What is it that you really want to know?"; + replies[12][6] = "Have you asked anyone else?"; + replies[12][7] = "Have you asked such questions before?"; + replies[12][8] = "What else comes to mind when you ask that?"; + replies[13][0] = "Names don't interest me."; + replies[13][1] = "I don't care about names -- please go on."; + replies[14][0] = "Is that the real reason?"; + replies[14][1] = "Don't any other reasons come to mind?"; + replies[14][2] = "Does that reason explain anything else?"; + replies[14][3] = "What other reasons might there be?"; + replies[15][0] = "Please don't apologize!"; + replies[15][1] = "Apologies are not necessary."; + replies[15][2] = "What feelings do you have when you apologize?"; + replies[15][3] = "Don't be so defensive!"; + replies[16][0] = "What does that dream suggest to you?"; + replies[16][1] = "Do you dream often?"; + replies[16][2] = "What persons appear in your dreams?"; + replies[16][3] = "Are you disturbed by your dreams?"; + replies[17][0] = "How do you do ...please state your problem."; + replies[18][0] = "You don't seem quite certain."; + replies[18][1] = "Why the uncertain tone?"; + replies[18][2] = "Can't you be more positive?"; + replies[18][3] = "You aren't sure?"; + replies[18][4] = "Don't you know?"; + replies[19][0] = "Are you saying no just to be negative?"; + replies[19][1] = "You are being a bit negative."; + replies[19][2] = "Why not?"; + replies[19][3] = "Are you sure?"; + replies[19][4] = "Why no?"; + replies[20][0] = "Why are you concerned about my*?"; + replies[20][1] = "What about your own*?"; + replies[21][0] = "Can you think of a specific example?"; + replies[21][1] = "When?"; + replies[21][2] = "What are you thinking of?"; + replies[21][3] = "Really, always?"; + replies[22][0] = "Do you really think so?"; + replies[22][1] = "But you are not sure you*?"; + replies[22][2] = "Do you doubt you*?"; + replies[23][0] = "In what way?"; + replies[23][1] = "What resemblance do you see?"; + replies[23][2] = "What does the similarity suggest to you?"; + replies[23][3] = "What other connections do you see?"; + replies[23][4] = "Could there really be some connection?"; + replies[23][5] = "How?"; + replies[23][6] = "You seem quite positive."; + replies[24][0] = "Are you sure?"; + replies[24][1] = "I see."; + replies[24][2] = "I understand."; + replies[25][0] = "Why do you bring up the topic of friends?"; + replies[25][1] = "Do your friends worry you?"; + replies[25][2] = "Do your friends pick on you?"; + replies[25][3] = "Are you sure you have any friends?"; + replies[25][4] = "Do you impose on your friends?"; + replies[25][5] = "Perhaps your love for friends worries you."; + replies[26][0] = "Do computers worry you?"; + replies[26][1] = "Are you talking about me in particular?"; + replies[26][2] = "Are you frightened by machines?"; + replies[26][3] = "Why do you mention computers?"; + replies[26][4] = "What do you think machines have to do with your problem?"; + replies[26][5] = "Don't you think computers can help people?"; + replies[26][6] = "What is it about machines that worries you?"; + replies[27][0] = "Do you sometimes feel uneasy without a smartphone?"; + replies[27][1] = "Have you had these phantasies before?"; + replies[27][2] = "Does the world seem more real for you via apps?"; + replies[28][0] = "Tell me more about your family."; + replies[28][1] = "Who else in your family*?"; + replies[28][2] = "What does family relations mean for you?"; + replies[28][3] = "Come on, How old are you?"; + setupReplies = replies; + + return setupReplies; +} +// Concept and lisp implementation published by Joseph Weizenbaum (MIT): +// "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +// Computational Linguistis 1(1966)9, pp. 36-45 +// Revision history: +// 2016-10-06 Initial version +// 2017-03-29 Two diagrams updated (comments translated to English) +// 2017-03-29 More keywords and replies added +// 2019-03-14 Replies and mapping reorganised for easier maintenance +// 2019-03-15 key map joined from keyword array and index map +// 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +// 2019-11-28 New global type "History" (to ensure a homogenous array) +int main(void) +{ + // BEGIN initialization for "History" + // END initialization for "History" + // BEGIN initialization for "KeyMapEntry" + // END initialization for "KeyMapEntry" + + // TODO: Check and accomplish variable declarations: + const char* replies[][/*???*/] = setupReplies(); + const char* reflexions[][2] = setupReflexions(); + const char* byePhrases[][2] = setupGoodByePhrases(); + const KeyMapEntry keyMap[] = setupKeywords(); + char* varPart; + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + char* userInput; + ??? replyRing; + char* reply; + int posAster; + int offsets[]; + ??? keyIndex; + bool isRepeated; + bool isGone; + // Stores the last five inputs of the user in a ring buffer, + // the second component is the rolling (over-)write index. + struct History history; + int findInfo[2]; + struct KeyMapEntry entry; + + + // TODO: + // For any input using the 'scanf' function you need to fill the first argument. + // http://en.wikipedia.org/wiki/Scanf#Format_string_specifications + + // TODO: + // For any output using the 'printf' function you need to fill the first argument: + // http://en.wikipedia.org/wiki/Printf#printf_format_placeholders + + // Title information + printf("TODO: specify format\n", "************* ELIZA **************"); + printf("TODO: specify format\n", "* Original design by J. Weizenbaum"); + printf("TODO: specify format\n", "**********************************"); + printf("TODO: specify format\n", "* Adapted for Basic on IBM PC by"); + printf("TODO: specify format\n", "* - Patricia Danielson"); + printf("TODO: specify format\n", "* - Paul Hashfield"); + printf("TODO: specify format\n", "**********************************"); + printf("TODO: specify format\n", "* Adapted for Structorizer by"); + printf("TODO: specify format\n", "* - Kay Gürtzig / FH Erfurt 2016"); + printf("TODO: specify format\n", "* Version: 2.3 (2019-11-28)"); + printf("TODO: specify format\n", "* (Requires at least Structorizer 3.30-03 to run)"); + printf("TODO: specify format\n", "**********************************"); + // Stores the last five inputs of the user in a ring buffer, + // the second component is the rolling (over-)write index. + history.histArray[0] = ""; + history.histArray[1] = ""; + history.histArray[2] = ""; + history.histArray[3] = ""; + history.histArray[4] = ""; + history.histIndex = 0; + offsets[length(keyMap)-1] = 0; + isGone = false; + // Starter + printf("TODO: specify format\n", "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?"); + do { + scanf("TODO: specify format", &userInput); + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + userInput = normalizeInput(userInput); + isGone = checkGoodBye(userInput, byePhrases); + if (! isGone) { + reply = "Please don\'t repeat yourself!"; + isRepeated = checkRepetition(history, userInput); + if (! isRepeated) { + findInfo = findKeyword(keyMap, userInput); + keyIndex = findInfo[0]; + if (keyIndex < 0) { + // Should never happen... + keyIndex = length(keyMap)-1; + } + entry = keyMap[keyIndex]; + // Variable part of the reply + varPart = ""; + if (length(entry.keyword) > 0) { + varPart = conjugateStrings(userInput, entry.keyword, findInfo[1], reflexions); + } + replyRing = replies[entry.index]; + reply = replyRing[offsets[keyIndex]]; + offsets[keyIndex] = (offsets[keyIndex] + 1) % length(replyRing); + posAster = pos("*", reply); + if (posAster > 0) { + if (varPart == " ") { + reply = "You will have to elaborate more for me to help you."; + } + else { + delete(reply, posAster, 1); + insert(varPart, reply, posAster); + } + } + reply = adjustSpelling(reply); + } + printf("TODO: specify format\n", reply); + } + } while (!(isGone)); + + return 0; +} diff --git a/samples/export/C/SORTING_TEST_MAIN.c b/samples/export/C/SORTING_TEST_MAIN.c index 75e03a3b..835b21e5 100644 --- a/samples/export/C/SORTING_TEST_MAIN.c +++ b/samples/export/C/SORTING_TEST_MAIN.c @@ -1,5 +1,5 @@ // program SORTING_TEST_MAIN -// Generated by Structorizer 3.30-02 +// Generated by Structorizer 3.30-03 // // Copyright (C) 2019-10-02 Kay Gürtzig // License: GPLv3-link @@ -24,7 +24,7 @@ // processed subrange) finds its final place at the end of the // subrange. // TODO: Revise the return type and declare the parameters. -void bubbleSort(/*type?*/ values) +void bubbleSort(??? values) { // TODO: Check and accomplish variable declarations: ??? temp; @@ -55,7 +55,7 @@ void bubbleSort(/*type?*/ values) // index range-1, restores heap property in the subtree at index i // again. // TODO: Revise the return type and declare the parameters. -void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) +void maxHeapify(??? heap, ??? i, ??? range) { // TODO: Check and accomplish variable declarations: ??? temp; @@ -93,7 +93,7 @@ void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) // This is not the most efficient algorithm (about half the swapping // might still be avoided) but it is pretty clear. // TODO: Revise the return type and declare the parameters. -int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /*type?*/ p) +int partition(??? values, ??? start, ??? stop, ??? p) { // TODO: Check and accomplish variable declarations: ??? seen; @@ -131,7 +131,7 @@ int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /*type?*/ p) // function testSorted(numbers): bool // Checks whether or not the passed-in array is (ascendingly) sorted. // TODO: Revise the return type and declare the parameters. -bool testSorted(/*type?*/ numbers) +bool testSorted(??? numbers) { // TODO: Check and accomplish variable declarations: bool isSorted; @@ -159,7 +159,7 @@ bool testSorted(/*type?*/ numbers) // (index >= length(heap) div 2) and goes then up towards // the root. // TODO: Revise the return type and declare the parameters. -int buildMaxHeap(/*type?*/ heap) +int buildMaxHeap(??? heap) { // TODO: Check and accomplish variable declarations: int lgth; @@ -179,7 +179,7 @@ int buildMaxHeap(/*type?*/ heap) // start is the first index of the subsequence to be sorted, // stop is the index BEHIND the subsequence to be sorted. // TODO: Revise the return type and declare the parameters. -int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) +int quickSort(??? values, ??? start, ??? stop) { // TODO: Check and accomplish variable declarations: ??? p; @@ -232,7 +232,7 @@ int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) // Sorts the array 'values´ of numbers according to he heap sort // algorithm // TODO: Revise the return type and declare the parameters. -int heapSort(/*type?*/ values) +int heapSort(??? values) { // TODO: Check and accomplish variable declarations: ??? maximum; @@ -260,13 +260,13 @@ int heapSort(/*type?*/ values) int main(void) { // TODO: Check and accomplish variable declarations: - ??? values3; - ??? values2; - ??? values1; + ??? values3[]; + ??? values2[]; + int values1[]; ??? show; - ??? ok3; - ??? ok2; - ??? ok1; + bool ok3; + bool ok2; + bool ok1; ??? modus; int i; ??? elementCount; @@ -299,7 +299,7 @@ int main(void) break; } } - // Kopiere das Array für exakte Vergleichbarkeit + // Copy the array for exact comparability for (i = 0; i <= elementCount-1; i += (1)) { values2[i] = values1[i]; values3[i] = values1[i]; diff --git a/samples/export/C/TextDemo.c b/samples/export/C/TextDemo.c new file mode 100644 index 00000000..7905ca62 --- /dev/null +++ b/samples/export/C/TextDemo.c @@ -0,0 +1,1308 @@ +// program TextDemo +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2019-10-10 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// + +#define _CRT_SECURE_NO_WARNINGS +#include +#include + +#include + + + +// function blank(h, colorNo) +// Draws a blank for font height h, ignoring the colorNo +// TODO: Revise the return type and declare the parameters. +void blank(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + + + width = h/2.0; + penUp(); + right(90); + forward(width); // color = ffffff + left(90); +} + +// function forward(len, color) +// TODO: Revise the return type and declare the parameters. +void forward(??? len, ??? color) +{ + // TODO: Check and accomplish variable declarations: + + switch (color) { + case 1: + forward(len); // color = ffffff + break; + case 2: + forward(len); // color = ff8080 + break; + case 3: + forward(len); // color = ffff80 + break; + case 4: + forward(len); // color = 80ff80 + break; + case 5: + forward(len); // color = 80ffff + break; + case 6: + forward(len); // color = 0080ff + break; + case 7: + forward(len); // color = ff80c0 + break; + case 8: + forward(len); // color = c0c0c0 + break; + case 9: + forward(len); // color = ff8000 + break; + case 10: + forward(len); // color = 8080ff + break; + } +} + +// function letterA(h, colorNo) +// Draws letter A in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterA(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle; + double hypo; + + + width = h/2.0; + hypo = sqrt(h*h + width*width/4.0); + rotAngle = toDegrees(atan(width/2.0/h)); + right(rotAngle); + forward(hypo/2.0, colorNo); + right(90 - rotAngle); + forward(width/2.0, colorNo); + penUp(); + backward(width/2.0); // color = ffffff + penDown(); + left(90 - rotAngle); + forward(hypo/2.0, colorNo); + left(2*rotAngle); + forward(-hypo, colorNo); + right(rotAngle); +} + +// function letterE(h, colorNo) +// Draws letter E in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterE(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + + + width = h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); // color = ffffff + left(90); + penDown(); + forward(width, colorNo); + left(90); +} + +// function letterF(h, colorNo) +// Draws letter F in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterF(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + + + width = h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); // color = ffffff + left(90); + forward(width); // color = ffffff + penDown(); + left(90); +} + +// function letterH(h, colorNo) +// Draws letter H in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterH(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + + + width = h/2.0; + forward(h, colorNo); + penUp(); + right(90); + forward(width); // color = ffffff + right(90); + penDown(); + forward(h/2.0, colorNo); + right(90); + forward(width, colorNo); + penUp(); + backward(width); // color = ffffff + left(90); + penDown(); + forward(h/2.0, colorNo); + left(180); +} + +// function letterI(h, colorNo) +// Draws letter I in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterI(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? c; + ??? b; + + + // Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + c = b / sqrt(2.0); + penUp(); + right(90); + forward(c); // color = ffffff + penDown(); + forward(b, colorNo); + penUp(); + backward(b/2.0); // color = ffffff + left(90); + penDown(); + forward(h, colorNo); + penUp(); + right(90); + backward(b/2.0); // color = ffffff + penDown(); + forward(b, colorNo); + penUp(); + forward(b/2 + c); // color = ffffff + left(90); + backward(h); // color = ffffff + penDown(); +} + +// function letterK(h, colorNo) +// Draws letter K in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterK(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + ??? diag; + + + width = h/2.0; + diag = h/sqrt(2.0); + forward(h, colorNo); + penUp(); + right(90); + forward(width); // color = ffffff + right(135); + penDown(); + forward(diag, colorNo); + left(90); + forward(diag, colorNo); + left(135); +} + +// function letterL(h, colorNo) +// Draws letter L in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterL(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + + + width = h/2.0; + forward(h, colorNo); + penUp(); + backward(h); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90); +} + +// function letterM(h, colorNo) +// Draws letter M in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterM(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle; + ??? hypo; + + + width = h/2.0; + hypo = sqrt(width*width + h*h)/2.0; + rotAngle = toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + left(rotAngle); + forward(-h, colorNo); +} + +// function letterN(h, colorNo) +// Draws letter N in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterN(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle; + double hypo; + + + width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(rotAngle); + forward(h, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// function letterT(h, colorNo) +// Draws letter T in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterT(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + + + width = h/2.0; + penUp(); + forward(h); // color = ffffff + penDown(); + right(90); + forward(width, colorNo); + penUp(); + backward(width/2.0); // color = ffffff + penDown(); + right(90); + forward(h, colorNo); + left(90); + penUp(); + forward(width/2.0); // color = ffffff + penDown(); + left(90); +} + +// function letterV(h, colorNo) +// Draws letter V in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterV(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle; + double hypo; + + + width = h/2.0; + hypo = sqrt(h*h + width*width/4.0); + rotAngle = toDegrees(atan(width/2.0/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); // color = ffffff + penDown(); +} + +// function letterW(h, colorNo) +// Draws letter W in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterW(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width_3; + ??? width; + double rotAngle; + double hypo; + + + width = h/2.0; + width_3 = width/3.0; + hypo = sqrt(width_3*width_3 + h*h); + rotAngle = toDegrees(atan(width_3/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width_3); // color = ffffff + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); // color = ffffff + penDown(); +} + +// function letterX(h, colorNo) +// Draws letter X in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterX(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle; + double hypo; + + + width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + right(rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width); // color = ffffff + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); +} + +// function letterY(h, colorNo) +// Draws letter Y in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterY(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle; + ??? hypo; + + + width = h/2.0; + hypo = sqrt(width*width + h*h)/2.0; + rotAngle = toDegrees(atan(width/h)); + penUp(); + forward(h); // color = ffffff + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); + penUp(); + backward(h/2.0); // color = ffffff + penDown(); + forward(h/2.0, colorNo); + right(rotAngle); + forward(hypo, colorNo); + left(rotAngle); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// function letterZ(h, colorNo) +// Draws letter Z in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterZ(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle; + double hypo; + + + width = h/2.0; + hypo = sqrt(width*width + h*h); + rotAngle = toDegrees(atan(width/h)); + penUp(); + forward(h); // color = ffffff + right(90); + penDown(); + forward(width, colorNo); + left(90-rotAngle); + forward(-hypo, colorNo); + right(90-rotAngle); + forward(width, colorNo); + left(90); +} + +// function polygonPart(a: double; n: integer; ctrclkws: boolean; nEdges: integer; color: int) +// Draws nEdges edges of a regular n-polygon with edge length a +// counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +// TODO: Revise the return type and declare the parameters. +void polygonPart(double a, int n, bool ctrclkws, int nEdges, int color) +{ + // TODO: Check and accomplish variable declarations: + ??? rotAngle; + int k; + + + rotAngle = 360.0/n; + if (ctrclkws) { + rotAngle = -rotAngle; + } + for (k = 1; k <= nEdges; k += (1)) { + right(rotAngle); + forward(a, color); + } +} + +// function charDummy(h, colorNo) +// Draws a dummy character (small centered square) with font height h and +// the colour encoded by colorNo +// TODO: Revise the return type and declare the parameters. +void charDummy(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + ??? d; + ??? c; + ??? b; + + + width = h / 2.0; + // Octagon edge length (here: edge lengzh of the square) + b = width / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + c = (width - b) / 2.0; + d = b / sqrt(2.0); + penUp(); + forward(h/2.0-b/2.0); // color = ffffff + right(90); + forward(c); // color = ffffff + right(90); + penDown(); + // Draws the square with edge length b + polygonPart(b, 4, true, 4, colorNo); + penUp(); + left(90); + forward(b + c); // color = ffffff + left(90); + backward(h/2.0-b/2.0); // color = ffffff + penDown(); +} + +// function comma(h, colorNo) +// Draws a comma in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void comma(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + double rotAngle; + ??? hypo; + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + rotAngle = toDegrees(atan(0.5)); + hypo = c * sqrt(1.25); + penUp(); + right(90); + forward((c+b)/2.0 + c); // color = ffffff + penDown(); + // Counterclockwise draw 3 edges of a square with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 3, colorNo); + left(90); + forward(c/2.0, colorNo); + right(90); + forward(c, colorNo); + left(180 - rotAngle); + forward(hypo, colorNo); + penUp(); + right(90 - rotAngle); + forward((c + b)/2.0); // color = ffffff + left(90); + penDown(); +} + +// function exclMk(h, colorNo) +// Draws an exclamation mark in the colour encoded by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void exclMk(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? width; + double rotAngle2; + // 360°/8 + int rotAngle; + ??? length2; + ??? length1; + double hypo; + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + width = h/2.0; + length1 = h - (b+c)/2.0; + length2 = length1 - 2*c; + hypo = sqrt(width*width/16.0 + length2*length2); + // 360°/8 + rotAngle = 45; + rotAngle2 = toDegrees(atan(width/4.0/length2)); + penUp(); + forward(length1); // color = ffffff + right(90); + forward(width/2.0); // color = ffffff + left(90 + rotAngle); + penDown(); + // Clockwise draw 5 edges of an octagon with edge length b/2 + // in the colour endcoded by colorNo + polygonPart(b/2.0, 8, false, 5, colorNo); + right(rotAngle2); + forward(hypo, colorNo); + left(2*rotAngle2); + forward(-hypo, colorNo); + penUp(); + forward(hypo); // color = ffffff + right(rotAngle2); + forward(c); // color = ffffff + left(90); + forward(c/2.0); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + backward(c); // color = ffffff + penDown(); +} + +// function fullSt(h, colorNo) +// Draws a full stop in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void fullSt(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + penUp(); + right(90); + forward((c+b)/2.0 + c); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + penDown(); +} + +// function letterB(h, colorNo) +// Draws letter B in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterB(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? c; + ??? b; + + + // Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the outer corner triangle of the octagon + c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + c); // color = ffffff + penDown(); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); +} + +// function letterC(h, colorNo) +// Draws letter C in the colour encoded by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterC(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + ??? c; + ??? b; + + + // Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the outer trinagle at the octagon corner + c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Clockwise draws 3 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + penUp(); + forward(2*b + 2*c); // color = ffffff + penDown(); + // Counterclockwise draws 4 edges of an octagon with edge length b + // iin the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); +} + +// function letterD(h, colorNo) +// Draws letter D in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterD(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + forward(b + 2*c, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); +} + +// function letterG(h, colorNo) +// Draws letter G in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterG(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? c; + ??? b; + + + // Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon. + c = b / sqrt(2.0); + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(c, colorNo); + left(90); + forward(b/2.0 + c, colorNo); + penUp(); + backward(b/2.0 + c); // color = ffffff + right(90); + forward(b + c); // color = ffffff + penDown(); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); +} + +// function letterJ(h, colorNo) +// Draws letter J in colour encoded by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterJ(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 3 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// function letterO(h, colorNo) +// Draws letter O in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterO(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? c; + ??? b; + + + // Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + c = b / sqrt(2.0); + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + penDown(); + left(90); +} + +// function letterP(h, colorNo) +// Draws letter P in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterP(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + ??? c; + ??? b; + + + // Octagon edge length + b = h * 0.5 / (sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + c = b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + backward(b + 2*c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + penDown(); + left(180); +} + +// function letterQ(h, colorNo) +// Draws letter Q in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterQ(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(b + 2*c); // color = ffffff + right(rotAngle); + backward(b); // color = ffffff + penDown(); + forward(b, colorNo); + left(90 + rotAngle); +} + +// function letterR(h, colorNo) +// Zeichnet den Buchstaben R von der Turtleposition aus +// mit Zeilenhöhe h +// TODO: Revise the return type and declare the parameters. +void letterR(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + left(90 + rotAngle); + forward(sqrt(2.0)*(b + 2*c), colorNo); + left(90 + rotAngle); +} + +// function letterS(h, colorNo) +// Draws letter S in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterS(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 6 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 6, colorNo); + // Clockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + right(rotAngle); + penUp(); + forward(2*b + 3*c); // color = ffffff + penDown(); + left(180); +} + +// function letterU(h, colorNo) +// Draws letter U in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void letterU(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + ??? c; + ??? b; + + + // edge length of a regular octagon + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(c); // color = ffffff + penDown(); + forward(h - c, colorNo); + penUp(); + backward(h-c); // color = ffffff + penDown(); + right(180); + // Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); // color = ffffff + penDown(); +} + +// function qstnMk(h, colorNo) +// Draws a question mark in colour specified by colorNo with font height h +// from the current turtle position. +// TODO: Revise the return type and declare the parameters. +void qstnMk(??? h, ??? colorNo) +{ + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + ??? c; + ??? b; + + + // Achteck-Kantenlänge + b = h * 0.5 / (sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + c = b / sqrt(2.0); + // 360°/8 + rotAngle = 45; + penUp(); + forward(h-c); // color = ffffff + penDown(); + // Counterclockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + forward(c, colorNo); + left(rotAngle); + forward(b/2.0, colorNo); + penUp(); + forward(c); // color = ffffff + left(90); + forward(c/2.0); // color = ffffff + penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); // color = ffffff + left(90); + backward(c); // color = ffffff + penDown(); +} + +// function drawText(text: string; h: integer; c: integer) +// Has the turtle draw the given string 'text´ with font height 'h´ (in +// pixels) and the colour coded by integer 'c´ from the current Turtle +// position to the Turtle canvas. If the turtle looks North then +// the text will be written rightwards. In the event, the turtle will be +// placed behind the text in original orientation (such that the next text +// would be written like a continuation. Colour codes: +// 1 = black +// 2 = red +// 3 = yellow +// 4 = green +// 5 = cyan +// 6 = blue +// 7 = pink +// 8 = grey +// 9 = orange +// 10 = violet +// All letters (ASCII) will be converted to uppercase, digits cannot +// be represented, the set of representable special characters is: +// '.', ',', '!', '?'. Other characters will be shown as a small +// centred square (dummy character). +// TODO: Revise the return type and declare the parameters. +void drawText(char* text, int h, int c) +{ + // TODO: Check and accomplish variable declarations: + char* letter; + int k; + ??? gap; + + + gap = h/10.0; + for (k = 1; k <= length(text); k += (1)) { + letter = uppercase(copy(text, k, 1)); + if (letter == ",") { + comma(h,c); + } + else { + // "," cannot be chacked against because the comma is misinterpreted + // as selector list separator. + switch (letter) { + case "A": + letterA(h,c); + break; + case "B": + letterB(h,c); + break; + case "C": + letterC(h,c); + break; + case "D": + letterD(h,c); + break; + case "E": + letterE(h,c); + break; + case "F": + letterF(h,c); + break; + case "G": + letterG(h,c); + break; + case "H": + letterH(h,c); + break; + case "I": + letterI(h,c); + break; + case "J": + letterJ(h,c); + break; + case "K": + letterK(h,c); + break; + case "L": + letterL(h,c); + break; + case "M": + letterM(h,c); + break; + case "N": + letterN(h,c); + break; + case "O": + letterO(h,c); + break; + case "P": + letterP(h,c); + break; + case "Q": + letterQ(h,c); + break; + case "R": + letterR(h,c); + break; + case "S": + letterS(h,c); + break; + case "T": + letterT(h,c); + break; + case "U": + letterU(h,c); + break; + case "V": + letterV(h,c); + break; + case "W": + letterW(h,c); + break; + case "X": + letterX(h,c); + break; + case "Y": + letterY(h,c); + break; + case "Z": + letterZ(h,c); + break; + case " ": + blank(h,c); + break; + case "!": + exclMk(h,c); + break; + case "?": + qstnMk(h,c); + break; + case ".": + fullSt(h,c); + break; + default: + charDummy(h,c); + } + } + right(90); + penUp(); + forward(gap); // color = ffffff + penDown(); + left(90); + } +} +// Demo program for routine drawText() +// Asks the user to enter a text, a wanted text height and colour, +// and then draws this string onto the turtle screen. Places every +// entered text to a new line. +int main(void) +{ + // TODO: Check and accomplish variable declarations: + int y; + ??? text; + ??? height; + ??? colour; + + + // TODO: + // For any input using the 'scanf' function you need to fill the first argument. + // http://en.wikipedia.org/wiki/Scanf#Format_string_specifications + + // TODO: + // For any output using the 'printf' function you need to fill the first argument: + // http://en.wikipedia.org/wiki/Printf#printf_format_placeholders + + printf("TODO: specify format\n", "This is a demo program for text writing with Turleizer."); + showTurtle(); + penDown(); + y = 0; + do { + printf("Enter some text (empty string to exit)"); scanf("TODO: specify format", &text); + // Make sure the content is interpreted as string + text = "" + text; + if (text != "") { + do { + printf("Height of the text (pixels)"); scanf("TODO: specify format", &height); + } while (!(height >= 5)); + do { + printf("Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"); scanf("TODO: specify format", &colour); + } while (!(colour >= 1 && colour <= 10)); + y = y + height + 2; + gotoXY(0, y - 2); + drawText(text, height, colour); + } + } while (!(text == "")); + gotoXY(0, y + 15); + drawText("Thank you, bye.", 10, 4); + hideTurtle(); + + return 0; +} diff --git a/samples/export/Java/ELIZA_2.3.java b/samples/export/Java/ELIZA_2.3.java new file mode 100644 index 00000000..215955ed --- /dev/null +++ b/samples/export/Java/ELIZA_2.3.java @@ -0,0 +1,477 @@ +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2018-05-14 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// + +import java.util.Scanner; + +import javax.swing.*; +/** + * Concept and lisp implementation published by Joseph Weizenbaum (MIT): + * "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: + * Computational Linguistis 1(1966)9, pp. 36-45 + * Revision history: + * 2016-10-06 Initial version + * 2017-03-29 Two diagrams updated (comments translated to English) + * 2017-03-29 More keywords and replies added + * 2019-03-14 Replies and mapping reorganised for easier maintenance + * 2019-03-15 key map joined from keyword array and index map + * 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") + * 2019-11-28 New global type "History" (to ensure a homogenous array) + */ +public class ELIZA { + + + // histArray contains the most recent user replies as ring buffer; + // histIndex is the index where the next reply is to be stored (= index of the oldest + // cached user reply). + // Note: The depth of the history is to be specified by initializing a variable of this type, + // e.g. for a history of depth 5: + // myhistory <- History{{"", "", "", "", ""}, 0} + private class History{ + public String[] histArray; + public int histIndex; + public History(String[] p_histArray, int p_histIndex) + { + histArray = p_histArray; + histIndex = p_histIndex; + } + }; + + // Associates a key word in the text with an index in the reply ring array + private class KeyMapEntry{ + public String keyword; + public int index; + public KeyMapEntry(String p_keyword, int p_index) + { + keyword = p_keyword; + index = p_index; + } + }; + + + /** + * @param args + */ + public static void main(String[] args) { + // BEGIN initialization for "History" + // END initialization for "History" + // BEGIN initialization for "KeyMapEntry" + // END initialization for "KeyMapEntry" + + // TODO: Check and accomplish variable declarations: + String varPart; + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + String userInput; + String reply; + int posAster; + int[] offsets; + boolean isRepeated; + boolean isGone; + int[] findInfo; + + + // TODO: You may have to modify input instructions, + // e.g. by replacing nextLine() with a more suitable call + // according to the variable type, say nextInt(). + + // Title information + System.out.println("************* ELIZA **************"); + System.out.println("* Original design by J. Weizenbaum"); + System.out.println("**********************************"); + System.out.println("* Adapted for Basic on IBM PC by"); + System.out.println("* - Patricia Danielson"); + System.out.println("* - Paul Hashfield"); + System.out.println("**********************************"); + System.out.println("* Adapted for Structorizer by"); + System.out.println("* - Kay Gürtzig / FH Erfurt 2016"); + System.out.println("* Version: 2.3 (2019-11-28)"); + System.out.println("* (Requires at least Structorizer 3.30-03 to run)"); + System.out.println("**********************************"); + // Stores the last five inputs of the user in a ring buffer, + // the second component is the rolling (over-)write index. + History history = new History(new String[]{"", "", "", "", ""}, 0); + final String[][] replies = setupReplies(); + final String[][] reflexions = setupReflexions(); + final String[][] byePhrases = setupGoodByePhrases(); + final KeyMapEntry[] keyMap = setupKeywords(); + offsets[length(keyMap)-1] = 0; + isGone = false; + // Starter + System.out.println("Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?"); + do { + userInput = (new Scanner(System.in)).nextLine(); + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + userInput = normalizeInput(userInput); + isGone = checkGoodBye(userInput, byePhrases); + if (! isGone) { + reply = "Please don\'t repeat yourself!"; + isRepeated = checkRepetition(history, userInput); + if (! isRepeated) { + findInfo = findKeyword(keyMap, userInput); + ??? keyIndex = findInfo[0]; + if (keyIndex < 0) { + // Should never happen... + keyIndex = length(keyMap)-1; + } + KeyMapEntry entry = keyMap[keyIndex]; + // Variable part of the reply + varPart = ""; + if (length(entry.keyword) > 0) { + varPart = conjugateStrings(userInput, entry.keyword, findInfo[1], reflexions); + } + ??? replyRing = replies[entry.index]; + reply = replyRing[offsets[keyIndex]]; + offsets[keyIndex] = (offsets[keyIndex] + 1) % length(replyRing); + posAster = pos("*", reply); + if (posAster > 0) { + if (varPart == " ") { + reply = "You will have to elaborate more for me to help you."; + } + else { + delete(reply, posAster, 1); + insert(varPart, reply, posAster); + } + } + reply = adjustSpelling(reply); + } + System.out.println(reply); + } + } while (!(isGone)); + } + + /** + * Cares for correct letter case among others + * @param sentence + * @return + */ + private static String adjustSpelling(String sentence) { + // TODO: Check and accomplish variable declarations: + String word; + String start; + String result; + int position; + + + result = sentence; + position = 1; + while ((position <= length(sentence)) && (copy(sentence, position, 1) == " ")) { + position = position + 1; + } + if (position <= length(sentence)) { + start = copy(sentence, 1, position); + delete(result, 1, position); + insert(uppercase(start), result, 1); + } + for (String word : new String[]{" i ", " i\'"}) { + position = pos(word, result); + while (position > 0) { + delete(result, position+1, 1); + insert("I", result, position+1); + position = pos(word, result); + } + } + + return result; + } + + /** + * Checks whether the given text contains some kind of + * good-bye phrase inducing the end of the conversation + * and if so writes a correspding good-bye message and + * returns true, otherwise false + * @param text + * @param phrases + * @return + */ + private static boolean checkGoodBye(String text, String[][] phrases) { + // TODO: Check and accomplish variable declarations: + boolean saidBye; + String[] pair; + + + for (@String pair : phrases) { + if (pos(pair[0], text) > 0) { + saidBye = true; + System.out.println(pair[1]); + return true; + } + } + return false; + } + + /** + * Checks whether newInput has occurred among the recently cached + * input strings in the histArray component of history and updates the history. + * @param history + * @param newInput + * @return + */ + private static boolean checkRepetition(History history, String newInput) { + // TODO: Check and accomplish variable declarations: + int histDepth; + boolean hasOccurred; + + + hasOccurred = false; + if (length(newInput) > 4) { + histDepth = length(history.histArray); + for (int i = 0; i <= histDepth-1; i += (1)) { + if (newInput == history.histArray[i]) { + hasOccurred = true; + } + } + history.histArray[history.histIndex] = newInput; + history.histIndex = (history.histIndex + 1) % (histDepth); + } + return hasOccurred; + } + + /** + * @param sentence + * @param key + * @param keyPos + * @param flexions + * @return + */ + private static String conjugateStrings(String sentence, String key, int keyPos, String[][] flexions) { + // TODO: Check and accomplish variable declarations: + String right; + String result; + int position; + String[] pair; + String left; + + + result = " " + copy(sentence, keyPos + length(key), length(sentence)) + " "; + for (@String pair : flexions) { + left = ""; + right = result; + position = pos(pair[0], right); + while (position > 0) { + left = left + copy(right, 1, position-1) + pair[1]; + right = copy(right, position + length(pair[0]), length(right)); + position = pos(pair[0], right); + } + result = left + right; + } + // Eliminate multiple spaces + position = pos(" ", result); + while (position > 0) { + result = copy(result, 1, position-1) + copy(result, position+1, length(result)); + position = pos(" ", result); + } + + return result; + } + + /** + * Looks for the occurrence of the first of the strings + * contained in keywords within the given sentence (in + * array order). + * Returns an array of + * 0: the index of the first identified keyword (if any, otherwise -1), + * 1: the position inside sentence (0 if not found) + * @param keyMap + * @param sentence + * @return + */ + private static int[] findKeyword(final array of KeyMapEntry keyMap, String sentence) { + // TODO: Check and accomplish variable declarations: + int[] result; + int position; + int i; + + + // Contains the index of the keyword and its position in sentence + result = new int[]{-1, 0}; + i = 0; + while ((result[0] < 0) && (i < length(keyMap))) { + KeyMapEntry entry = keyMap[i]; + position = pos(entry.keyword, sentence); + if (position > 0) { + result[0] = i; + result[1] = position; + } + i = i+1; + } + + return result; + } + + /** + * Converts the sentence to lowercase, eliminates all + * interpunction (i.e. ',', '.', ';'), and pads the + * sentence among blanks + * @param sentence + * @return + */ + private static String normalizeInput(String sentence) { + // TODO: Check and accomplish variable declarations: + String symbol; + String result; + int position; + + + sentence = lowercase(sentence); + for (String symbol : new String[]{'.', ',', ';', '!', '?'}) { + position = pos(symbol, sentence); + while (position > 0) { + sentence = copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)); + position = pos(symbol, sentence); + } + } + result = " " + sentence + " "; + + return result; + } + + /** + * @return + */ + private static String[][] setupGoodByePhrases() { + // TODO: Check and accomplish variable declarations: + String[][] phrases; + + + phrases[0] = new String[]{" shut", "Okay. If you feel that way I\'ll shut up. ... Your choice."}; + phrases[1] = new String[]{"bye", "Well, let\'s end our talk for now. See you later. Bye."}; + return phrases; + } + + /** + * The lower the index the higher the rank of the keyword (search is sequential). + * The index of the first keyword found in a user sentence maps to a respective + * reply ring as defined in `setupReplies()´. + * @return + */ + private static KeyMapEntry[] setupKeywords() { + // TODO: Check and accomplish variable declarations: + // The empty key string (last entry) is the default clause - will always be found + KeyMapEntry[] keywords; + + + // The empty key string (last entry) is the default clause - will always be found + keywords[39] = new KeyMapEntry("", 29); + keywords[0] = new KeyMapEntry("can you ", 0); + keywords[1] = new KeyMapEntry("can i ", 1); + keywords[2] = new KeyMapEntry("you are ", 2); + keywords[3] = new KeyMapEntry("you\'re ", 2); + keywords[4] = new KeyMapEntry("i don't ", 3); + keywords[5] = new KeyMapEntry("i feel ", 4); + keywords[6] = new KeyMapEntry("why don\'t you ", 5); + keywords[7] = new KeyMapEntry("why can\'t i ", 6); + keywords[8] = new KeyMapEntry("are you ", 7); + keywords[9] = new KeyMapEntry("i can\'t ", 8); + keywords[10] = new KeyMapEntry("i am ", 9); + keywords[11] = new KeyMapEntry("i\'m ", 9); + keywords[12] = new KeyMapEntry("you ", 10); + keywords[13] = new KeyMapEntry("i want ", 11); + keywords[14] = new KeyMapEntry("what ", 12); + keywords[15] = new KeyMapEntry("how ", 12); + keywords[16] = new KeyMapEntry("who ", 12); + keywords[17] = new KeyMapEntry("where ", 12); + keywords[18] = new KeyMapEntry("when ", 12); + keywords[19] = new KeyMapEntry("why ", 12); + keywords[20] = new KeyMapEntry("name ", 13); + keywords[21] = new KeyMapEntry("cause ", 14); + keywords[22] = new KeyMapEntry("sorry ", 15); + keywords[23] = new KeyMapEntry("dream ", 16); + keywords[24] = new KeyMapEntry("hello ", 17); + keywords[25] = new KeyMapEntry("hi ", 17); + keywords[26] = new KeyMapEntry("maybe ", 18); + keywords[27] = new KeyMapEntry(" no", 19); + keywords[28] = new KeyMapEntry("your ", 20); + keywords[29] = new KeyMapEntry("always ", 21); + keywords[30] = new KeyMapEntry("think ", 22); + keywords[31] = new KeyMapEntry("alike ", 23); + keywords[32] = new KeyMapEntry("yes ", 24); + keywords[33] = new KeyMapEntry("friend ", 25); + keywords[34] = new KeyMapEntry("computer", 26); + keywords[35] = new KeyMapEntry("bot ", 26); + keywords[36] = new KeyMapEntry("smartphone", 27); + keywords[37] = new KeyMapEntry("father ", 28); + keywords[38] = new KeyMapEntry("mother ", 28); + return keywords; + } + + /** + * Returns an array of pairs of mutualy substitutable + * @return + */ + private static String[][] setupReflexions() { + // TODO: Check and accomplish variable declarations: + String[][] reflexions; + + + reflexions[0] = new String[]{" are ", " am "}; + reflexions[1] = new String[]{" were ", " was "}; + reflexions[2] = new String[]{" you ", " I "}; + reflexions[3] = new String[]{" your", " my"}; + reflexions[4] = new String[]{" i\'ve ", " you\'ve "}; + reflexions[5] = new String[]{" i\'m ", " you\'re "}; + reflexions[6] = new String[]{" me ", " you "}; + reflexions[7] = new String[]{" my ", " your "}; + reflexions[8] = new String[]{" i ", " you "}; + reflexions[9] = new String[]{" am ", " are "}; + return reflexions; + } + + /** + * This routine sets up the reply rings addressed by the key words defined in + * routine `setupKeywords()´ and mapped hitherto by the cross table defined + * in `setupMapping()´ + * @return + */ + private static String[][] setupReplies() { + // TODO: Check and accomplish variable declarations: + String[][] setupReplies; + + + String[][] replies; + // We start with the highest index for performance reasons + // (is to avoid frequent array resizing) + replies[29] = new String[]{"Say, do you have any psychological problems?", "What does that suggest to you?", "I see.", "I'm not sure I understand you fully.", "Come come elucidate your thoughts.", "Can you elaborate on that?", "That is quite interesting."}; + replies[0] = new String[]{"Don't you believe that I can*?", "Perhaps you would like to be like me?", "You want me to be able to*?"}; + replies[1] = new String[]{"Perhaps you don't want to*?", "Do you want to be able to*?"}; + replies[2] = new String[]{"What makes you think I am*?", "Does it please you to believe I am*?", "Perhaps you would like to be*?", "Do you sometimes wish you were*?"}; + replies[3] = new String[]{"Don't you really*?", "Why don't you*?", "Do you wish to be able to*?", "Does that trouble you*?"}; + replies[4] = new String[]{"Do you often feel*?", "Are you afraid of feeling*?", "Do you enjoy feeling*?"}; + replies[5] = new String[]{"Do you really believe I don't*?", "Perhaps in good time I will*.", "Do you want me to*?"}; + replies[6] = new String[]{"Do you think you should be able to*?", "Why can't you*?"}; + replies[7] = new String[]{"Why are you interested in whether or not I am*?", "Would you prefer if I were not*?", "Perhaps in your fantasies I am*?"}; + replies[8] = new String[]{"How do you know you can't*?", "Have you tried?", "Perhaps you can now*."}; + replies[9] = new String[]{"Did you come to me because you are*?", "How long have you been*?", "Do you believe it is normal to be*?", "Do you enjoy being*?"}; + replies[10] = new String[]{"We were discussing you--not me.", "Oh, I*.", "You're not really talking about me, are you?"}; + replies[11] = new String[]{"What would it mean to you if you got*?", "Why do you want*?", "Suppose you soon got*...", "What if you never got*?", "I sometimes also want*."}; + replies[12] = new String[]{"Why do you ask?", "Does that question interest you?", "What answer would please you the most?", "What do you think?", "Are such questions on your mind often?", "What is it that you really want to know?", "Have you asked anyone else?", "Have you asked such questions before?", "What else comes to mind when you ask that?"}; + replies[13] = new String[]{"Names don't interest me.", "I don't care about names -- please go on."}; + replies[14] = new String[]{"Is that the real reason?", "Don't any other reasons come to mind?", "Does that reason explain anything else?", "What other reasons might there be?"}; + replies[15] = new String[]{"Please don't apologize!", "Apologies are not necessary.", "What feelings do you have when you apologize?", "Don't be so defensive!"}; + replies[16] = new String[]{"What does that dream suggest to you?", "Do you dream often?", "What persons appear in your dreams?", "Are you disturbed by your dreams?"}; + replies[17] = new String[]{"How do you do ...please state your problem."}; + replies[18] = new String[]{"You don't seem quite certain.", "Why the uncertain tone?", "Can't you be more positive?", "You aren't sure?", "Don't you know?"}; + replies[19] = new String[]{"Are you saying no just to be negative?", "You are being a bit negative.", "Why not?", "Are you sure?", "Why no?"}; + replies[20] = new String[]{"Why are you concerned about my*?", "What about your own*?"}; + replies[21] = new String[]{"Can you think of a specific example?", "When?", "What are you thinking of?", "Really, always?"}; + replies[22] = new String[]{"Do you really think so?", "But you are not sure you*?", "Do you doubt you*?"}; + replies[23] = new String[]{"In what way?", "What resemblance do you see?", "What does the similarity suggest to you?", "What other connections do you see?", "Could there really be some connection?", "How?", "You seem quite positive."}; + replies[24] = new String[]{"Are you sure?", "I see.", "I understand."}; + replies[25] = new String[]{"Why do you bring up the topic of friends?", "Do your friends worry you?", "Do your friends pick on you?", "Are you sure you have any friends?", "Do you impose on your friends?", "Perhaps your love for friends worries you."}; + replies[26] = new String[]{"Do computers worry you?", "Are you talking about me in particular?", "Are you frightened by machines?", "Why do you mention computers?", "What do you think machines have to do with your problem?", "Don't you think computers can help people?", "What is it about machines that worries you?"}; + replies[27] = new String[]{"Do you sometimes feel uneasy without a smartphone?", "Have you had these phantasies before?", "Does the world seem more real for you via apps?"}; + replies[28] = new String[]{"Tell me more about your family.", "Who else in your family*?", "What does family relations mean for you?", "Come on, How old are you?"}; + setupReplies = replies; + + return setupReplies; + } + +} diff --git a/samples/export/Java/SORTING_TEST_MAIN.java b/samples/export/Java/SORTING_TEST_MAIN.java index 5f8b4377..e8067857 100644 --- a/samples/export/Java/SORTING_TEST_MAIN.java +++ b/samples/export/Java/SORTING_TEST_MAIN.java @@ -1,4 +1,4 @@ -// Generated by Structorizer 3.30-02 +// Generated by Structorizer 3.30-03 // // Copyright (C) 2019-10-02 Kay Gürtzig // License: GPLv3-link @@ -29,9 +29,9 @@ public class SORTING_TEST_MAIN { */ public static void main(String[] args) { // =========== START PARALLEL WORKER DEFINITIONS ============ - class Worker4f085546_0 implements Callable { - private /*type?*/ values1; - public Worker4f085546_0(/*type?*/ values1) { + class Worker247e34b9_0 implements Callable { + private int[] values1; + public Worker247e34b9_0(int[] values1) { this.values1 = values1; } public Object[] call() throws Exception { @@ -41,10 +41,10 @@ public Object[] call() throws Exception { } }; - class Worker4f085546_1 implements Callable { - private /*type?*/ values2; - private /*type?*/ elementCount; - public Worker4f085546_1(/*type?*/ values2, /*type?*/ elementCount) { + class Worker247e34b9_1 implements Callable { + private ???[] values2; + private ??? elementCount; + public Worker247e34b9_1(???[] values2, ??? elementCount) { this.values2 = values2; this.elementCount = elementCount; } @@ -55,9 +55,9 @@ public Object[] call() throws Exception { } }; - class Worker4f085546_2 implements Callable { - private /*type?*/ values3; - public Worker4f085546_2(/*type?*/ values3) { + class Worker247e34b9_2 implements Callable { + private ???[] values3; + public Worker247e34b9_2(???[] values3) { this.values3 = values3; } public Object[] call() throws Exception { @@ -69,10 +69,13 @@ public Object[] call() throws Exception { // ============ END PARALLEL WORKER DEFINITIONS ============= // TODO: Check and accomplish variable declarations: - ??? values3; - ??? values2; - ??? values1; + ???[] values3; + ???[] values2; + int[] values1; ??? show; + boolean ok3; + boolean ok2; + boolean ok1; ??? modus; ??? elementCount; @@ -100,7 +103,7 @@ public Object[] call() throws Exception { break; } } - // Kopiere das Array für exakte Vergleichbarkeit + // Copy the array for exact comparability for (int i = 0; i <= elementCount-1; i += (1)) { values2[i] = values1[i]; values3[i] = values1[i]; @@ -113,21 +116,21 @@ public Object[] call() throws Exception { ExecutorService pool = Executors.newFixedThreadPool(3); // ----------------- START THREAD 0 ----------------- - Future future4f085546_0 = pool.submit( new Worker4f085546_0(values1) ); + Future future247e34b9_0 = pool.submit( new Worker247e34b9_0(values1) ); // ----------------- START THREAD 1 ----------------- - Future future4f085546_1 = pool.submit( new Worker4f085546_1(values2, elementCount) ); + Future future247e34b9_1 = pool.submit( new Worker247e34b9_1(values2, elementCount) ); // ----------------- START THREAD 2 ----------------- - Future future4f085546_2 = pool.submit( new Worker4f085546_2(values3) ); + Future future247e34b9_2 = pool.submit( new Worker247e34b9_2(values3) ); Object[] results; // ----------------- AWAIT THREAD 0 ----------------- - results = future4f085546_0.get(); + results = future247e34b9_0.get(); // ----------------- AWAIT THREAD 1 ----------------- - results = future4f085546_1.get(); + results = future247e34b9_1.get(); // ----------------- AWAIT THREAD 2 ----------------- - results = future4f085546_2.get(); + results = future247e34b9_2.get(); pool.shutdown(); } catch (Exception ex) { System.err.println(ex.getMessage()); ex.printStackTrace(); } @@ -164,16 +167,16 @@ public Object[] call() throws Exception { * subrange. * @param values */ - private static void bubbleSort(/*type?*/ values) { + private static void bubbleSort(??? values) { // TODO: Check and accomplish variable declarations: - ende = length(values) - 2; + ??? ende = length(values) - 2; do { // The index of the most recent swapping (-1 means no swapping done). - posSwapped = -1; + ??? posSwapped = -1; for (int i = 0; i <= ende; i += (1)) { if (values[i] > values[i+1]) { - temp = values[i]; + ??? temp = values[i]; values[i] = values[i+1]; values[i+1] = temp; posSwapped = i; @@ -192,14 +195,14 @@ private static void bubbleSort(/*type?*/ values) { * @param i * @param range */ - private static void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) { + private static void maxHeapify(??? heap, ??? i, ??? range) { // TODO: Check and accomplish variable declarations: // Indices of left and right child of node i - right = (i+1) * 2; - left = right - 1; + ??? right = (i+1) * 2; + ??? left = right - 1; // Index of the (local) maximum - max = i; + ??? max = i; if (left < range && heap[left] > heap[i]) { max = left; } @@ -207,7 +210,7 @@ private static void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) { max = right; } if (max != i) { - temp = heap[i]; + ??? temp = heap[i]; heap[i] = heap[max]; heap[max] = temp; maxHeapify(heap, max, range); @@ -229,10 +232,10 @@ private static void maxHeapify(/*type?*/ heap, /*type?*/ i, /*type?*/ range) { * @param p * @return */ - private static int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, /*type?*/ p) { + private static int partition(??? values, ??? start, ??? stop, ??? p) { // TODO: Check and accomplish variable declarations: - pivot = values[p]; + ??? pivot = values[p]; // Tausche das Pivot-Element an den start values[p] = values[start]; values[start] = pivot; @@ -242,7 +245,7 @@ private static int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, stop = stop - 1; // Still unseen elements? while (stop >= start) { - seen = values[start]; + ??? seen = values[start]; if (values[start] <= pivot) { // Swap pivot element with start element values[p] = seen; @@ -265,7 +268,7 @@ private static int partition(/*type?*/ values, /*type?*/ start, /*type?*/ stop, * @param numbers * @return */ - private static boolean testSorted(/*type?*/ numbers) { + private static boolean testSorted(??? numbers) { // TODO: Check and accomplish variable declarations: boolean isSorted; int i; @@ -294,7 +297,7 @@ private static boolean testSorted(/*type?*/ numbers) { * @param heap * @return */ - private static int buildMaxHeap(/*type?*/ heap) { + private static int buildMaxHeap(??? heap) { // TODO: Check and accomplish variable declarations: int lgth; @@ -316,13 +319,13 @@ private static int buildMaxHeap(/*type?*/ heap) { * @param stop * @return */ - private static int quickSort(/*type?*/ values, /*type?*/ start, /*type?*/ stop) { + private static int quickSort(??? values, ??? start, ??? stop) { // =========== START PARALLEL WORKER DEFINITIONS ============ - class Worker3dfab37d_0 implements Callable { - private /*type?*/ values; - private /*type?*/ start; - private /*type?*/ p; - public Worker3dfab37d_0(/*type?*/ values, /*type?*/ start, /*type?*/ p) { + class Worker7fed1521_0 implements Callable { + private ??? values; + private ??? start; + private ??? p; + public Worker7fed1521_0(??? values, ??? start, ??? p) { this.values = values; this.start = start; this.p = p; @@ -335,11 +338,11 @@ public Object[] call() throws Exception { } }; - class Worker3dfab37d_1 implements Callable { - private /*type?*/ values; - private /*type?*/ p; - private /*type?*/ stop; - public Worker3dfab37d_1(/*type?*/ values, /*type?*/ p, /*type?*/ stop) { + class Worker7fed1521_1 implements Callable { + private ??? values; + private ??? p; + private ??? stop; + public Worker7fed1521_1(??? values, ??? p, ??? stop) { this.values = values; this.p = p; this.stop = stop; @@ -359,7 +362,7 @@ public Object[] call() throws Exception { if (stop >= start + 2) { // Select a pivot element, be p its index. // (here: randomly chosen element out of start ... stop-1) - p = random(stop-start) + start; + ??? p = random(stop-start) + start; // Partition the array into smaller and greater elements // Get the resulting (and final) position of the pivot element // Partition the array into smaller and greater elements @@ -374,16 +377,16 @@ public Object[] call() throws Exception { ExecutorService pool = Executors.newFixedThreadPool(2); // ----------------- START THREAD 0 ----------------- - Future future3dfab37d_0 = pool.submit( new Worker3dfab37d_0(values, start, p) ); + Future future7fed1521_0 = pool.submit( new Worker7fed1521_0(values, start, p) ); // ----------------- START THREAD 1 ----------------- - Future future3dfab37d_1 = pool.submit( new Worker3dfab37d_1(values, p, stop) ); + Future future7fed1521_1 = pool.submit( new Worker7fed1521_1(values, p, stop) ); Object[] results; // ----------------- AWAIT THREAD 0 ----------------- - results = future3dfab37d_0.get(); + results = future7fed1521_0.get(); // ----------------- AWAIT THREAD 1 ----------------- - results = future3dfab37d_1.get(); + results = future7fed1521_1.get(); pool.shutdown(); } catch (Exception ex) { System.err.println(ex.getMessage()); ex.printStackTrace(); } @@ -402,7 +405,7 @@ public Object[] call() throws Exception { * @param values * @return */ - private static int heapSort(/*type?*/ values) { + private static int heapSort(??? values) { // TODO: Check and accomplish variable declarations: int heapRange; @@ -412,7 +415,7 @@ private static int heapSort(/*type?*/ values) { for (int k = heapRange - 1; k >= 1; k += (-1)) { heapRange = heapRange - 1; // Swap the maximum value (root of the heap) to the heap end - maximum = values[0]; + ??? maximum = values[0]; values[0] = values[heapRange]; values[heapRange] = maximum; maxHeapify(values, 0, heapRange); diff --git a/samples/export/Java/TextDemo.java b/samples/export/Java/TextDemo.java new file mode 100644 index 00000000..46846b0f --- /dev/null +++ b/samples/export/Java/TextDemo.java @@ -0,0 +1,1268 @@ +// Generated by Structorizer 3.30-03 +// +// Copyright (C) 2019-10-10 Kay Gürtzig +// License: GPLv3-link +// GNU General Public License (V 3) +// https://www.gnu.org/licenses/gpl.html +// http://www.gnu.de/documents/gpl.de.html +// + +import java.util.Scanner; + +import javax.swing.*; +// TODO: Download the turtle package from https://structorizer.fisch.lu and put it into this project +import lu.fisch.turtle.adapters.Turtleizer; +/** + * Demo program for routine drawText() + * Asks the user to enter a text, a wanted text height and colour, + * and then draws this string onto the turtle screen. Places every + * entered text to a new line. + */ +public class TextDemo { + + + + /** + * @param args + */ + public static void main(String[] args) { + // TODO: Check and accomplish variable declarations: + int y; + ??? height; + ??? colour; + + + // TODO: You may have to modify input instructions, + // e.g. by replacing nextLine() with a more suitable call + // according to the variable type, say nextInt(). + + System.out.println("This is a demo program for text writing with Turleizer."); + Turtleizer.showTurtle(); + Turtleizer.penDown(); + y = 0; + do { + System.out.print("Enter some text (empty string to exit)"); text = (new Scanner(System.in)).nextLine(); + // Make sure the content is interpreted as string + ??? text = "" + text; + if (text != "") { + do { + System.out.print("Height of the text (pixels)"); height = (new Scanner(System.in)).nextLine(); + } while (!(height >= 5)); + do { + System.out.print("Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"); colour = (new Scanner(System.in)).nextLine(); + } while (!(colour >= 1 && colour <= 10)); + y = y + height + 2; + Turtleizer.gotoXY(0, y - 2); + drawText(text, height, colour); + } + } while (!(text == "")); + Turtleizer.gotoXY(0, y + 15); + drawText("Thank you, bye.", 10, 4); + + /** + * Draws a blank for font height h, ignoring the colorNo + * @param h + * @param colorNo + */ + private static void blank(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + Turtleizer.penUp(); + Turtleizer.right(90); + Turtleizer.forward(width, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + } + + /** + * @param len + * @param color + */ + private static void forward(??? len, ??? color) { + // TODO: Check and accomplish variable declarations: + + switch (color) { + case 1: + Turtleizer.forward(len, java.awt.Color.decode("0xffffff")); + break; + case 2: + Turtleizer.forward(len, java.awt.Color.decode("0xff8080")); + break; + case 3: + Turtleizer.forward(len, java.awt.Color.decode("0xffff80")); + break; + case 4: + Turtleizer.forward(len, java.awt.Color.decode("0x80ff80")); + break; + case 5: + Turtleizer.forward(len, java.awt.Color.decode("0x80ffff")); + break; + case 6: + Turtleizer.forward(len, java.awt.Color.decode("0x0080ff")); + break; + case 7: + Turtleizer.forward(len, java.awt.Color.decode("0xff80c0")); + break; + case 8: + Turtleizer.forward(len, java.awt.Color.decode("0xc0c0c0")); + break; + case 9: + Turtleizer.forward(len, java.awt.Color.decode("0xff8000")); + break; + case 10: + Turtleizer.forward(len, java.awt.Color.decode("0x8080ff")); + break; + } + } + + /** + * Draws letter A in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterA(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = Math.sqrt(h*h + width*width/4.0); + rotAngle = Math.toDegrees(Math.atan(width/2.0/h)); + Turtleizer.right(rotAngle); + Turtleizer.forward(hypo/2.0, colorNo); + Turtleizer.right(90 - rotAngle); + Turtleizer.forward(width/2.0, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(width/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(90 - rotAngle); + Turtleizer.forward(hypo/2.0, colorNo); + Turtleizer.left(2*rotAngle); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(rotAngle); + } + + /** + * Draws letter E in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterE(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + Turtleizer.forward(h, colorNo); + Turtleizer.right(90); + Turtleizer.forward(width, colorNo); + Turtleizer.right(90); + Turtleizer.penUp(); + Turtleizer.forward(h/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.penDown(); + Turtleizer.forward(width, colorNo); + Turtleizer.left(90); + Turtleizer.penUp(); + Turtleizer.forward(h/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.penDown(); + Turtleizer.forward(width, colorNo); + Turtleizer.left(90); + } + + /** + * Draws letter F in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterF(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + Turtleizer.forward(h, colorNo); + Turtleizer.right(90); + Turtleizer.forward(width, colorNo); + Turtleizer.right(90); + Turtleizer.penUp(); + Turtleizer.forward(h/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.penDown(); + Turtleizer.forward(width, colorNo); + Turtleizer.left(90); + Turtleizer.penUp(); + Turtleizer.forward(h/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(width, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(90); + } + + /** + * Draws letter H in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterH(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + Turtleizer.forward(h, colorNo); + Turtleizer.penUp(); + Turtleizer.right(90); + Turtleizer.forward(width, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.penDown(); + Turtleizer.forward(h/2.0, colorNo); + Turtleizer.right(90); + Turtleizer.forward(width, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(width, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.penDown(); + Turtleizer.forward(h/2.0, colorNo); + Turtleizer.left(180); + } + + /** + * Draws letter I in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterI(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / Math.sqrt(2.0); + Turtleizer.penUp(); + Turtleizer.right(90); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.forward(b, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(b/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.penDown(); + Turtleizer.forward(h, colorNo); + Turtleizer.penUp(); + Turtleizer.right(90); + Turtleizer.backward(b/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.forward(b, colorNo); + Turtleizer.penUp(); + Turtleizer.forward(b/2 + c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws letter K in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterK(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + ??? diag = h/Math.sqrt(2.0); + Turtleizer.forward(h, colorNo); + Turtleizer.penUp(); + Turtleizer.right(90); + Turtleizer.forward(width, java.awt.Color.decode("0xffffff")); + Turtleizer.right(135); + Turtleizer.penDown(); + Turtleizer.forward(diag, colorNo); + Turtleizer.left(90); + Turtleizer.forward(diag, colorNo); + Turtleizer.left(135); + } + + /** + * Draws letter L in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterL(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + Turtleizer.forward(h, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.penDown(); + Turtleizer.forward(width, colorNo); + Turtleizer.left(90); + } + + /** + * Draws letter M in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterM(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + ??? width = h/2.0; + ??? hypo = Math.sqrt(width*width + h*h)/2.0; + rotAngle = Math.toDegrees(Math.atan(width/h)); + Turtleizer.forward(h, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(2*rotAngle); + Turtleizer.forward(hypo, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.forward(-h, colorNo); + } + + /** + * Draws letter N in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterN(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = Math.sqrt(width*width + h*h); + rotAngle = Math.toDegrees(Math.atan(width/h)); + Turtleizer.forward(h, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(rotAngle); + Turtleizer.forward(h, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws letter T in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterT(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h/2.0; + Turtleizer.penUp(); + Turtleizer.forward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(90); + Turtleizer.forward(width, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(width/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(90); + Turtleizer.forward(h, colorNo); + Turtleizer.left(90); + Turtleizer.penUp(); + Turtleizer.forward(width/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(90); + } + + /** + * Draws letter V in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterV(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = Math.sqrt(h*h + width*width/4.0); + rotAngle = Math.toDegrees(Math.atan(width/2.0/h)); + Turtleizer.penUp(); + Turtleizer.forward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.left(rotAngle); + Turtleizer.penDown(); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(2*rotAngle); + Turtleizer.forward(hypo, colorNo); + Turtleizer.penUp(); + Turtleizer.left(rotAngle); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws letter W in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterW(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + ??? width_3 = width/3.0; + hypo = Math.sqrt(width_3*width_3 + h*h); + rotAngle = Math.toDegrees(Math.atan(width_3/h)); + Turtleizer.penUp(); + Turtleizer.forward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.left(rotAngle); + Turtleizer.penDown(); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(2*rotAngle); + Turtleizer.forward(hypo, colorNo); + Turtleizer.penUp(); + Turtleizer.left(90+rotAngle); + Turtleizer.forward(width_3, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90-rotAngle); + Turtleizer.penDown(); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(2*rotAngle); + Turtleizer.forward(hypo, colorNo); + Turtleizer.penUp(); + Turtleizer.left(rotAngle); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws letter X in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterX(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = Math.sqrt(width*width + h*h); + rotAngle = Math.toDegrees(Math.atan(width/h)); + Turtleizer.right(rotAngle); + Turtleizer.forward(hypo, colorNo); + Turtleizer.penUp(); + Turtleizer.left(90+rotAngle); + Turtleizer.forward(width, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90-rotAngle); + Turtleizer.penDown(); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(rotAngle); + } + + /** + * Draws letter Y in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterY(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + ??? width = h/2.0; + ??? hypo = Math.sqrt(width*width + h*h)/2.0; + rotAngle = Math.toDegrees(Math.atan(width/h)); + Turtleizer.penUp(); + Turtleizer.forward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.left(rotAngle); + Turtleizer.penDown(); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(rotAngle); + Turtleizer.penUp(); + Turtleizer.backward(h/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.forward(h/2.0, colorNo); + Turtleizer.right(rotAngle); + Turtleizer.forward(hypo, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.penUp(); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws letter Z in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterZ(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + double hypo; + + + ??? width = h/2.0; + hypo = Math.sqrt(width*width + h*h); + rotAngle = Math.toDegrees(Math.atan(width/h)); + Turtleizer.penUp(); + Turtleizer.forward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.penDown(); + Turtleizer.forward(width, colorNo); + Turtleizer.left(90-rotAngle); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.right(90-rotAngle); + Turtleizer.forward(width, colorNo); + Turtleizer.left(90); + } + + /** + * Draws nEdges edges of a regular n-polygon with edge length a + * counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. + * @param a + * @param n + * @param ctrclkws + * @param nEdges + * @param color + */ + private static void polygonPart(double a, int n, boolean ctrclkws, int nEdges, int color) { + // TODO: Check and accomplish variable declarations: + + ??? rotAngle = 360.0/n; + if (ctrclkws) { + rotAngle = -rotAngle; + } + for (int k = 1; k <= nEdges; k += (1)) { + Turtleizer.right(rotAngle); + Turtleizer.forward(a, color); + } + } + + /** + * Draws a dummy character (small centered square) with font height h and + * the colour encoded by colorNo + * @param h + * @param colorNo + */ + private static void charDummy(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + ??? width = h / 2.0; + // Octagon edge length (here: edge lengzh of the square) + ??? b = width / (Math.sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = (width - b) / 2.0; + ??? d = b / Math.sqrt(2.0); + Turtleizer.penUp(); + Turtleizer.forward(h/2.0-b/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.penDown(); + // Draws the square with edge length b + polygonPart(b, 4, true, 4, colorNo); + Turtleizer.penUp(); + Turtleizer.left(90); + Turtleizer.forward(b + c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.backward(h/2.0-b/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws a comma in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void comma(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + rotAngle = Math.toDegrees(Math.atan(0.5)); + ??? hypo = c * Math.sqrt(1.25); + Turtleizer.penUp(); + Turtleizer.right(90); + Turtleizer.forward((c+b)/2.0 + c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Counterclockwise draw 3 edges of a square with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 3, colorNo); + Turtleizer.left(90); + Turtleizer.forward(c/2.0, colorNo); + Turtleizer.right(90); + Turtleizer.forward(c, colorNo); + Turtleizer.left(180 - rotAngle); + Turtleizer.forward(hypo, colorNo); + Turtleizer.penUp(); + Turtleizer.right(90 - rotAngle); + Turtleizer.forward((c + b)/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.penDown(); + } + + /** + * Draws an exclamation mark in the colour encoded by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void exclMk(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + double rotAngle2; + // 360°/8 + int rotAngle; + double hypo; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + ??? width = h/2.0; + ??? length1 = h - (b+c)/2.0; + ??? length2 = length1 - 2*c; + hypo = Math.sqrt(width*width/16.0 + length2*length2); + // 360°/8 + rotAngle = 45; + rotAngle2 = Math.toDegrees(Math.atan(width/4.0/length2)); + Turtleizer.penUp(); + Turtleizer.forward(length1, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.forward(width/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90 + rotAngle); + Turtleizer.penDown(); + // Clockwise draw 5 edges of an octagon with edge length b/2 + // in the colour endcoded by colorNo + polygonPart(b/2.0, 8, false, 5, colorNo); + Turtleizer.right(rotAngle2); + Turtleizer.forward(hypo, colorNo); + Turtleizer.left(2*rotAngle2); + Turtleizer.forward(-hypo, colorNo); + Turtleizer.penUp(); + Turtleizer.forward(hypo, java.awt.Color.decode("0xffffff")); + Turtleizer.right(rotAngle2); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(c/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + Turtleizer.penUp(); + Turtleizer.forward((c + b)/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.backward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws a full stop in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void fullSt(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + Turtleizer.penUp(); + Turtleizer.right(90); + Turtleizer.forward((c+b)/2.0 + c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, true, 4, colorNo); + Turtleizer.penUp(); + Turtleizer.forward((c + b)/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.penDown(); + } + + /** + * Draws letter B in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterB(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Cathetus of the outer corner triangle of the octagon + ??? c = b / Math.sqrt(2.0); + Turtleizer.forward(h, colorNo); + Turtleizer.right(90); + Turtleizer.forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + Turtleizer.forward(c, colorNo); + Turtleizer.penUp(); + Turtleizer.left(180); + Turtleizer.forward(b + c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo); + Turtleizer.forward(c, colorNo); + Turtleizer.penUp(); + Turtleizer.left(180); + Turtleizer.forward(b + 2*c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(90); + } + + /** + * Draws letter C in the colour encoded by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterC(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Octagon edge length + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Cathetus of the outer trinagle at the octagon corner + ??? c = b / Math.sqrt(2.0); + // 360°/8 + rotAngle = 45; + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(180); + // Clockwise draws 3 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.penUp(); + Turtleizer.forward(2*b + 2*c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Counterclockwise draws 4 edges of an octagon with edge length b + // iin the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + Turtleizer.forward(b + 2*c, colorNo); + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(b + 2*c, colorNo); + Turtleizer.penDown(); + Turtleizer.left(90); + } + + /** + * Draws letter D in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterD(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + Turtleizer.forward(h, colorNo); + Turtleizer.right(90); + Turtleizer.forward(c+b, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + Turtleizer.forward(b + 2*c, colorNo); + // Clockwise draw 2 edges of an octagon with edge length b in the colour + // encoded by colorNo + polygonPart(b, 8, false, 2, colorNo); + Turtleizer.forward(c, colorNo); + Turtleizer.penUp(); + Turtleizer.left(180); + Turtleizer.forward(b + 2*c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(90); + } + + /** + * Draws letter G in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterG(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon. + ??? c = b / Math.sqrt(2.0); + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + Turtleizer.forward(c, colorNo); + Turtleizer.left(90); + Turtleizer.forward(b/2.0 + c, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(b/2.0 + c, java.awt.Color.decode("0xffffff")); + Turtleizer.right(90); + Turtleizer.forward(b + c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Counterclockwise draw 4 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + Turtleizer.forward(b + 2*c, colorNo); + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(b + 2*c, colorNo); + Turtleizer.penDown(); + Turtleizer.left(90); + } + + /** + * Draws letter J in colour encoded by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterJ(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + // 360°/8 + rotAngle = 45; + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(180); + // Counterclockwise draw 3 edges of an octagon with edge length b in + // the colour encoded by colorNo + polygonPart(b, 8, true, 3, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.forward(h - c, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws letter O in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterO(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / Math.sqrt(2.0); + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + Turtleizer.forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + Turtleizer.forward(b + 2*c, colorNo); + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(b + 2*c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(90); + } + + /** + * Draws letter P in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterP(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + + // Octagon edge length + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Cathetus of the corner triangle outside the octagon + ??? c = b / Math.sqrt(2.0); + Turtleizer.forward(h, colorNo); + Turtleizer.right(90); + Turtleizer.forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + Turtleizer.forward(c, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(b + 2*c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(b + 2*c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(180); + } + + /** + * Draws letter Q in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterQ(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + // 360°/8 + rotAngle = 45; + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(180); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + Turtleizer.forward(b + 2*c, colorNo); + // Counterclockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo); + Turtleizer.forward(b + 2*c, colorNo); + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(b + 2*c, java.awt.Color.decode("0xffffff")); + Turtleizer.right(rotAngle); + Turtleizer.backward(b, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.forward(b, colorNo); + Turtleizer.left(90 + rotAngle); + } + + /** + * Zeichnet den Buchstaben R von der Turtleposition aus + * mit Zeilenhöhe h + * @param h + * @param colorNo + */ + private static void letterR(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + // 360°/8 + rotAngle = 45; + Turtleizer.forward(h, colorNo); + Turtleizer.right(90); + Turtleizer.forward(c+b, colorNo); + // Clockwise draw 4 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo); + Turtleizer.forward(c, colorNo); + Turtleizer.left(90 + rotAngle); + Turtleizer.forward(Math.sqrt(2.0)*(b + 2*c), colorNo); + Turtleizer.left(90 + rotAngle); + } + + /** + * Draws letter S in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterS(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + // 360°/8 + rotAngle = 45; + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(180); + // Counterclockwise draw 6 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, true, 6, colorNo); + // Clockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + Turtleizer.right(rotAngle); + Turtleizer.penUp(); + Turtleizer.forward(2*b + 3*c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(180); + } + + /** + * Draws letter U in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void letterU(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // edge length of a regular octagon + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + // 360°/8 + rotAngle = 45; + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.forward(h - c, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(h-c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.right(180); + // Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart(b, 8, true, 3, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.forward(h - c, colorNo); + Turtleizer.penUp(); + Turtleizer.backward(h, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Draws a question mark in colour specified by colorNo with font height h + * from the current turtle position. + * @param h + * @param colorNo + */ + private static void qstnMk(??? h, ??? colorNo) { + // TODO: Check and accomplish variable declarations: + // 360°/8 + int rotAngle; + + + // Achteck-Kantenlänge + ??? b = h * 0.5 / (Math.sqrt(2.0) + 1); + // Eckenlänge außen am Achteck + ??? c = b / Math.sqrt(2.0); + // 360°/8 + rotAngle = 45; + Turtleizer.penUp(); + Turtleizer.forward(h-c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Counterclockwise draw 5 edges of an octagon with edge length b + // in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo); + Turtleizer.forward(c, colorNo); + Turtleizer.left(rotAngle); + Turtleizer.forward(b/2.0, colorNo); + Turtleizer.penUp(); + Turtleizer.forward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.forward(c/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + // Counterclockwise draw all 4 edges of a squarfe with edge length c + // in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo); + Turtleizer.penUp(); + Turtleizer.forward((c + b)/2.0, java.awt.Color.decode("0xffffff")); + Turtleizer.left(90); + Turtleizer.backward(c, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + } + + /** + * Has the turtle draw the given string 'text´ with font height 'h´ (in + * pixels) and the colour coded by integer 'c´ from the current Turtle + * position to the Turtle canvas. If the turtle looks North then + * the text will be written rightwards. In the event, the turtle will be + * placed behind the text in original orientation (such that the next text + * would be written like a continuation. Colour codes: + * 1 = black + * 2 = red + * 3 = yellow + * 4 = green + * 5 = cyan + * 6 = blue + * 7 = pink + * 8 = grey + * 9 = orange + * 10 = violet + * All letters (ASCII) will be converted to uppercase, digits cannot + * be represented, the set of representable special characters is: + * '.', ',', '!', '?'. Other characters will be shown as a small + * centred square (dummy character). + * @param text + * @param h + * @param c + */ + private static void drawText(String text, int h, int c) { + // TODO: Check and accomplish variable declarations: + String letter; + + + ??? gap = h/10.0; + for (int k = 1; k <= length(text); k += (1)) { + letter = uppercase(copy(text, k, 1)); + if (letter == ",") { + comma(h,c); + } + else { + // "," cannot be chacked against because the comma is misinterpreted + // as selector list separator. + switch (letter) { + case "A": + letterA(h,c); + break; + case "B": + letterB(h,c); + break; + case "C": + letterC(h,c); + break; + case "D": + letterD(h,c); + break; + case "E": + letterE(h,c); + break; + case "F": + letterF(h,c); + break; + case "G": + letterG(h,c); + break; + case "H": + letterH(h,c); + break; + case "I": + letterI(h,c); + break; + case "J": + letterJ(h,c); + break; + case "K": + letterK(h,c); + break; + case "L": + letterL(h,c); + break; + case "M": + letterM(h,c); + break; + case "N": + letterN(h,c); + break; + case "O": + letterO(h,c); + break; + case "P": + letterP(h,c); + break; + case "Q": + letterQ(h,c); + break; + case "R": + letterR(h,c); + break; + case "S": + letterS(h,c); + break; + case "T": + letterT(h,c); + break; + case "U": + letterU(h,c); + break; + case "V": + letterV(h,c); + break; + case "W": + letterW(h,c); + break; + case "X": + letterX(h,c); + break; + case "Y": + letterY(h,c); + break; + case "Z": + letterZ(h,c); + break; + case " ": + blank(h,c); + break; + case "!": + exclMk(h,c); + break; + case "?": + qstnMk(h,c); + break; + case ".": + fullSt(h,c); + break; + default: + charDummy(h,c); + } + } + Turtleizer.right(90); + Turtleizer.penUp(); + Turtleizer.forward(gap, java.awt.Color.decode("0xffffff")); + Turtleizer.penDown(); + Turtleizer.left(90); + } + } + Turtleizer.hideTurtle(); + } + +} diff --git a/samples/export/Js/ELIZA_2.3.js b/samples/export/Js/ELIZA_2.3.js new file mode 100644 index 00000000..c58e4f80 --- /dev/null +++ b/samples/export/Js/ELIZA_2.3.js @@ -0,0 +1,403 @@ + diff --git a/samples/export/Js/SORTING_TEST_MAIN.js b/samples/export/Js/SORTING_TEST_MAIN.js index a2835521..62a8d1ab 100644 --- a/samples/export/Js/SORTING_TEST_MAIN.js +++ b/samples/export/Js/SORTING_TEST_MAIN.js @@ -1,6 +1,6 @@ diff --git a/samples/export/Oberon/ELIZA_2.3.Mod b/samples/export/Oberon/ELIZA_2.3.Mod new file mode 100644 index 00000000..070c751c --- /dev/null +++ b/samples/export/Oberon/ELIZA_2.3.Mod @@ -0,0 +1,670 @@ +MODULE ELIZA; +IMPORT dummy0815; +IMPORT In, Out; +(* + * Concept and lisp implementation published by Joseph Weizenbaum (MIT): + * "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: + * Computational Linguistis 1(1966)9, pp. 36-45 + * Revision history: + * 2016-10-06 Initial version + * 2017-03-29 Two diagrams updated (comments translated to English) + * 2017-03-29 More keywords and replies added + * 2019-03-14 Replies and mapping reorganised for easier maintenance + * 2019-03-15 key map joined from keyword array and index map + * 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") + * 2019-11-28 New global type "History" (to ensure a homogenous array) + *) +(* Generated by Structorizer 3.30-03 *) +(* *) +(* Copyright (C) 2018-05-14 Kay Gürtzig *) +(* License: GPLv3-link *) +(* GNU General Public License (V 3) *) +(* https://www.gnu.org/licenses/gpl.html *) +(* http://www.gnu.de/documents/gpl.de.html *) +(* *) + +TYPE + (* histArray contains the most recent user replies as ring buffer; *) + (* histIndex is the index where the next reply is to be stored (= index of the oldest *) + (* cached user reply). *) + (* Note: The depth of the history is to be specified by initializing a variable of this type, *) + (* e.g. for a history of depth 5: *) + (* myhistory <- History{{"", "", "", "", ""}, 0} *) + History = RECORD + histArray: ARRAY OF ARRAY 100 OF CHAR; + histIndex: INTEGER + END; + + (* Associates a key word in the text with an index in the reply ring array *) + KeyMapEntry = RECORD + keyword: ARRAY 100 OF CHAR; + index: INTEGER + END; + +VAR + index29f23747: INTEGER; + array29f23747: ARRAY 5 OF ARRAY 100 OF CHAR; + index55f0bd09: INTEGER; + index3cd00c5b: INTEGER; + index7507a2dd: INTEGER; + array7507a2dd: ARRAY 2 OF ARRAY 100 OF CHAR; + (* TODO: check and accomplish variable declarations *) + varPart: ARRAY 100 OF CHAR; + (* Converts the input to lowercase, cuts out interpunctation *) + (* and pads the string *) + userInput: ARRAY 100 OF CHAR; + replyRing: ???; (* FIXME! *) + reply: ARRAY 100 OF CHAR; + posAster: INTEGER; + offsets: ARRAY OF INTEGER; + (* Should never happen... *) + keyIndex: ???; (* FIXME! *) + isRepeated: BOOLEAN; + isGone: BOOLEAN; + (* Stores the last five inputs of the user in a ring buffer, *) + (* the second component is the rolling (over-)write index. *) + history: History; + findInfo: ARRAY 2 OF INTEGER; + entry: KeyMapEntry; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE adjustSpelling*(sentence: ARRAY 100 OF CHAR): ARRAY 100 OF CHAR; +(* + * Cares for correct letter case among others + *) +VAR + (* TODO: check and accomplish variable declarations *) + word: ARRAY 100 OF CHAR; + start: ARRAY 100 OF CHAR; + result: ARRAY 100 OF CHAR; + position: INTEGER; +BEGIN + result := sentence; + position := 1; + WHILE (position <= length(sentence)) & (copy(sentence, position, 1) = " ") DO + position := position + 1; + END; + IF position <= length(sentence) THEN + start := copy(sentence, 1, position); + delete(result, 1, position); + insert(CAP(start), result, 1); + END; + array7507a2dd[0] := " i "; + array7507a2dd[1] := " i\'"; + FOR index7507a2dd := 0 TO 1 DO + word := array7507a2dd[index7507a2dd]; + position := pos(word, result); + WHILE position > 0 DO + delete(result, position+1, 1); + insert("I", result, position+1); + position := pos(word, result); + END; + END; + RETURN result; +END adjustSpelling; + +PROCEDURE checkGoodBye*(text: ARRAY 100 OF CHAR; VAR phrases: ARRAY OF ARRAY 2 OF ARRAY 100 OF CHAR): BOOLEAN; +(* + * Checks whether the given text contains some kind of + * good-bye phrase inducing the end of the conversation + * and if so writes a correspding good-bye message and + * returns true, otherwise false + *) +VAR + (* TODO: check and accomplish variable declarations *) + saidBye: BOOLEAN; + pair: ARRAY OF ARRAY 100 OF CHAR; +BEGIN + FOR index3cd00c5b := 0 TO LEN(phrases)-1 DO + pair := phrases[index3cd00c5b]; + IF pos(pair[0], text) > 0 THEN + saidBye := true; + (* TODO: Replace "TYPE" by the the actual Out procedure name for this type and add a length argument where needed! *) + Out.TYPE(pair[1]); + Out.Ln; + RETURN true; + END; + END; + RETURN false; +END checkGoodBye; + +PROCEDURE checkRepetition*(history: History; VAR newInput: ARRAY 100 OF CHAR): BOOLEAN; +(* + * Checks whether newInput has occurred among the recently cached + * input strings in the histArray component of history and updates the history. + *) +VAR + (* TODO: check and accomplish variable declarations *) + i: INTEGER; + histDepth: INTEGER; + hasOccurred: BOOLEAN; +BEGIN + hasOccurred := false; + IF length(newInput) > 4 THEN + histDepth := length(history.histArray); + FOR i := 0 TO histDepth-1 DO + IF newInput = history.histArray[i] THEN + hasOccurred := true; + END; + END; + history.histArray[history.histIndex] := newInput; + history.histIndex := (history.histIndex + 1) MOD (histDepth); + END; + RETURN hasOccurred; +END checkRepetition; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE conjugateStrings*(sentence, key: ARRAY 100 OF CHAR; keyPos: INTEGER; VAR flexions: ARRAY OF ARRAY 2 OF ARRAY 100 OF CHAR): ARRAY 100 OF CHAR; +VAR + (* TODO: check and accomplish variable declarations *) + right: ARRAY 100 OF CHAR; + result: ARRAY 100 OF CHAR; + position: INTEGER; + pair: ARRAY OF ARRAY 100 OF CHAR; + left: ARRAY 100 OF CHAR; +BEGIN + result := " " + copy(sentence, keyPos + length(key), length(sentence)) + " "; + FOR index55f0bd09 := 0 TO LEN(flexions)-1 DO + pair := flexions[index55f0bd09]; + left := ""; + right := result; + position := pos(pair[0], right); + WHILE position > 0 DO + left := left + copy(right, 1, position-1) + pair[1]; + right := copy(right, position + length(pair[0]), length(right)); + position := pos(pair[0], right); + END; + result := left + right; + END; + (* Eliminate multiple spaces *) + position := pos(" ", result); + WHILE position > 0 DO + result := copy(result, 1, position-1) + copy(result, position+1, length(result)); + position := pos(" ", result); + END; + RETURN result; +END conjugateStrings; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE findKeyword*(keyMap: const ARRAY OF KeyMapEntry; VAR sentence: ARRAY 100 OF CHAR): ARRAY 2 OF INTEGER; +(* + * Looks for the occurrence of the first of the strings + * contained in keywords within the given sentence (in + * array order). + * Returns an array of + * 0: the index of the first identified keyword (if any, otherwise -1), + * 1: the position inside sentence (0 if not found) + *) +CONST + keyMap = null; + +VAR + (* TODO: check and accomplish variable declarations *) + result: ARRAY 2 OF INTEGER; + position: INTEGER; + i: INTEGER; + entry: KeyMapEntry; +BEGIN + (* Contains the index of the keyword and its position in sentence *) + (* Hint: Automatically decomposed array initialization *) + result[0] := -1; + result[1] := 0; + i := 0; + WHILE (result[0] < 0) & (i < length(keyMap)) DO + entry := keyMap[i]; + position := pos(entry.keyword, sentence); + IF position > 0 THEN + result[0] := i; + result[1] := position; + END; + i := i+1; + END; + RETURN result; +END findKeyword; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE normalizeInput*(sentence: ARRAY 100 OF CHAR): ARRAY 100 OF CHAR; +(* + * Converts the sentence to lowercase, eliminates all + * interpunction (i.e. ',', '.', ';'), and pads the + * sentence among blanks + *) +VAR + (* TODO: check and accomplish variable declarations *) + symbol: ARRAY 100 OF CHAR; + result: ARRAY 100 OF CHAR; + position: INTEGER; +BEGIN + sentence := lowercase(sentence); + array29f23747[0] := '.'; + array29f23747[1] := ','; + array29f23747[2] := ';'; + array29f23747[3] := '!'; + array29f23747[4] := '?'; + FOR index29f23747 := 0 TO 4 DO + symbol := array29f23747[index29f23747]; + position := pos(symbol, sentence); + WHILE position > 0 DO + sentence := copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)); + position := pos(symbol, sentence); + END; + END; + result := " " + sentence + " "; + RETURN result; +END normalizeInput; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE setupGoodByePhrases*(): ARRAY OF ARRAY 2 OF ARRAY 100 OF CHAR; +VAR + (* TODO: check and accomplish variable declarations *) + phrases: ARRAY OF ARRAY 2 OF ARRAY 100 OF CHAR; +BEGIN + (* Hint: Automatically decomposed array initialization *) + phrases[0, 0] := " shut"; + phrases[0, 1] := "Okay. If you feel that way I\'ll shut up. ... Your choice."; + (* Hint: Automatically decomposed array initialization *) + phrases[1, 0] := "bye"; + phrases[1, 1] := "Well, let\'s end our talk for now. See you later. Bye."; + RETURN phrases; +END setupGoodByePhrases; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE setupKeywords*(): ARRAY OF KeyMapEntry; +(* + * The lower the index the higher the rank of the keyword (search is sequential). + * The index of the first keyword found in a user sentence maps to a respective + * reply ring as defined in `setupReplies()´. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* The empty key string (last entry) is the default clause - will always be found *) + keywords: ARRAY OF KeyMapEntry; +BEGIN + (* The empty key string (last entry) is the default clause - will always be found *) + keywords[39].keyword := ""; + keywords[39].index := 29; + keywords[0].keyword := "can you "; + keywords[0].index := 0; + keywords[1].keyword := "can i "; + keywords[1].index := 1; + keywords[2].keyword := "you are "; + keywords[2].index := 2; + keywords[3].keyword := "you\'re "; + keywords[3].index := 2; + keywords[4].keyword := "i don't "; + keywords[4].index := 3; + keywords[5].keyword := "i feel "; + keywords[5].index := 4; + keywords[6].keyword := "why don\'t you "; + keywords[6].index := 5; + keywords[7].keyword := "why can\'t i "; + keywords[7].index := 6; + keywords[8].keyword := "are you "; + keywords[8].index := 7; + keywords[9].keyword := "i can\'t "; + keywords[9].index := 8; + keywords[10].keyword := "i am "; + keywords[10].index := 9; + keywords[11].keyword := "i\'m "; + keywords[11].index := 9; + keywords[12].keyword := "you "; + keywords[12].index := 10; + keywords[13].keyword := "i want "; + keywords[13].index := 11; + keywords[14].keyword := "what "; + keywords[14].index := 12; + keywords[15].keyword := "how "; + keywords[15].index := 12; + keywords[16].keyword := "who "; + keywords[16].index := 12; + keywords[17].keyword := "where "; + keywords[17].index := 12; + keywords[18].keyword := "when "; + keywords[18].index := 12; + keywords[19].keyword := "why "; + keywords[19].index := 12; + keywords[20].keyword := "name "; + keywords[20].index := 13; + keywords[21].keyword := "cause "; + keywords[21].index := 14; + keywords[22].keyword := "sorry "; + keywords[22].index := 15; + keywords[23].keyword := "dream "; + keywords[23].index := 16; + keywords[24].keyword := "hello "; + keywords[24].index := 17; + keywords[25].keyword := "hi "; + keywords[25].index := 17; + keywords[26].keyword := "maybe "; + keywords[26].index := 18; + keywords[27].keyword := " no"; + keywords[27].index := 19; + keywords[28].keyword := "your "; + keywords[28].index := 20; + keywords[29].keyword := "always "; + keywords[29].index := 21; + keywords[30].keyword := "think "; + keywords[30].index := 22; + keywords[31].keyword := "alike "; + keywords[31].index := 23; + keywords[32].keyword := "yes "; + keywords[32].index := 24; + keywords[33].keyword := "friend "; + keywords[33].index := 25; + keywords[34].keyword := "computer"; + keywords[34].index := 26; + keywords[35].keyword := "bot "; + keywords[35].index := 26; + keywords[36].keyword := "smartphone"; + keywords[36].index := 27; + keywords[37].keyword := "father "; + keywords[37].index := 28; + keywords[38].keyword := "mother "; + keywords[38].index := 28; + RETURN keywords; +END setupKeywords; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE setupReflexions*(): ARRAY OF ARRAY 2 OF ARRAY 100 OF CHAR; +(* + * Returns an array of pairs of mutualy substitutable + *) +VAR + (* TODO: check and accomplish variable declarations *) + reflexions: ARRAY OF ARRAY 2 OF ARRAY 100 OF CHAR; +BEGIN + (* Hint: Automatically decomposed array initialization *) + reflexions[0, 0] := " are "; + reflexions[0, 1] := " am "; + (* Hint: Automatically decomposed array initialization *) + reflexions[1, 0] := " were "; + reflexions[1, 1] := " was "; + (* Hint: Automatically decomposed array initialization *) + reflexions[2, 0] := " you "; + reflexions[2, 1] := " I "; + (* Hint: Automatically decomposed array initialization *) + reflexions[3, 0] := " your"; + reflexions[3, 1] := " my"; + (* Hint: Automatically decomposed array initialization *) + reflexions[4, 0] := " i\'ve "; + reflexions[4, 1] := " you\'ve "; + (* Hint: Automatically decomposed array initialization *) + reflexions[5, 0] := " i\'m "; + reflexions[5, 1] := " you\'re "; + (* Hint: Automatically decomposed array initialization *) + reflexions[6, 0] := " me "; + reflexions[6, 1] := " you "; + (* Hint: Automatically decomposed array initialization *) + reflexions[7, 0] := " my "; + reflexions[7, 1] := " your "; + (* Hint: Automatically decomposed array initialization *) + reflexions[8, 0] := " i "; + reflexions[8, 1] := " you "; + (* Hint: Automatically decomposed array initialization *) + reflexions[9, 0] := " am "; + reflexions[9, 1] := " are "; + RETURN reflexions; +END setupReflexions; + +(* TODO: Oberon doesn't permit to return arrays - pass the result in a different way! *) +PROCEDURE setupReplies*(): ARRAY OF ARRAY OF ARRAY 100 OF CHAR; +(* + * This routine sets up the reply rings addressed by the key words defined in + * routine `setupKeywords()´ and mapped hitherto by the cross table defined + * in `setupMapping()´ + *) +VAR + (* TODO: check and accomplish variable declarations *) + setupReplies: ARRAY OF ARRAY OF ARRAY 100 OF CHAR; + replies: ARRAY OF ARRAY OF ARRAY 100 OF CHAR; +BEGIN + (* We start with the highest index for performance reasons *) + (* (is to avoid frequent array resizing) *) + (* Hint: Automatically decomposed array initialization *) + replies[29, 0] := "Say, do you have any psychological problems?"; + replies[29, 1] := "What does that suggest to you?"; + replies[29, 2] := "I see."; + replies[29, 3] := "I'm not sure I understand you fully."; + replies[29, 4] := "Come come elucidate your thoughts."; + replies[29, 5] := "Can you elaborate on that?"; + replies[29, 6] := "That is quite interesting."; + (* Hint: Automatically decomposed array initialization *) + replies[0, 0] := "Don't you believe that I can*?"; + replies[0, 1] := "Perhaps you would like to be like me?"; + replies[0, 2] := "You want me to be able to*?"; + (* Hint: Automatically decomposed array initialization *) + replies[1, 0] := "Perhaps you don't want to*?"; + replies[1, 1] := "Do you want to be able to*?"; + (* Hint: Automatically decomposed array initialization *) + replies[2, 0] := "What makes you think I am*?"; + replies[2, 1] := "Does it please you to believe I am*?"; + replies[2, 2] := "Perhaps you would like to be*?"; + replies[2, 3] := "Do you sometimes wish you were*?"; + (* Hint: Automatically decomposed array initialization *) + replies[3, 0] := "Don't you really*?"; + replies[3, 1] := "Why don't you*?"; + replies[3, 2] := "Do you wish to be able to*?"; + replies[3, 3] := "Does that trouble you*?"; + (* Hint: Automatically decomposed array initialization *) + replies[4, 0] := "Do you often feel*?"; + replies[4, 1] := "Are you afraid of feeling*?"; + replies[4, 2] := "Do you enjoy feeling*?"; + (* Hint: Automatically decomposed array initialization *) + replies[5, 0] := "Do you really believe I don't*?"; + replies[5, 1] := "Perhaps in good time I will*."; + replies[5, 2] := "Do you want me to*?"; + (* Hint: Automatically decomposed array initialization *) + replies[6, 0] := "Do you think you should be able to*?"; + replies[6, 1] := "Why can't you*?"; + (* Hint: Automatically decomposed array initialization *) + replies[7, 0] := "Why are you interested in whether or not I am*?"; + replies[7, 1] := "Would you prefer if I were not*?"; + replies[7, 2] := "Perhaps in your fantasies I am*?"; + (* Hint: Automatically decomposed array initialization *) + replies[8, 0] := "How do you know you can't*?"; + replies[8, 1] := "Have you tried?"; + replies[8, 2] := "Perhaps you can now*."; + (* Hint: Automatically decomposed array initialization *) + replies[9, 0] := "Did you come to me because you are*?"; + replies[9, 1] := "How long have you been*?"; + replies[9, 2] := "Do you believe it is normal to be*?"; + replies[9, 3] := "Do you enjoy being*?"; + (* Hint: Automatically decomposed array initialization *) + replies[10, 0] := "We were discussing you--not me."; + replies[10, 1] := "Oh, I*."; + replies[10, 2] := "You're not really talking about me, are you?"; + (* Hint: Automatically decomposed array initialization *) + replies[11, 0] := "What would it mean to you if you got*?"; + replies[11, 1] := "Why do you want*?"; + replies[11, 2] := "Suppose you soon got*..."; + replies[11, 3] := "What if you never got*?"; + replies[11, 4] := "I sometimes also want*."; + (* Hint: Automatically decomposed array initialization *) + replies[12, 0] := "Why do you ask?"; + replies[12, 1] := "Does that question interest you?"; + replies[12, 2] := "What answer would please you the most?"; + replies[12, 3] := "What do you think?"; + replies[12, 4] := "Are such questions on your mind often?"; + replies[12, 5] := "What is it that you really want to know?"; + replies[12, 6] := "Have you asked anyone else?"; + replies[12, 7] := "Have you asked such questions before?"; + replies[12, 8] := "What else comes to mind when you ask that?"; + (* Hint: Automatically decomposed array initialization *) + replies[13, 0] := "Names don't interest me."; + replies[13, 1] := "I don't care about names -- please go on."; + (* Hint: Automatically decomposed array initialization *) + replies[14, 0] := "Is that the real reason?"; + replies[14, 1] := "Don't any other reasons come to mind?"; + replies[14, 2] := "Does that reason explain anything else?"; + replies[14, 3] := "What other reasons might there be?"; + (* Hint: Automatically decomposed array initialization *) + replies[15, 0] := "Please don't apologize!"; + replies[15, 1] := "Apologies are not necessary."; + replies[15, 2] := "What feelings do you have when you apologize?"; + replies[15, 3] := "Don't be so defensive!"; + (* Hint: Automatically decomposed array initialization *) + replies[16, 0] := "What does that dream suggest to you?"; + replies[16, 1] := "Do you dream often?"; + replies[16, 2] := "What persons appear in your dreams?"; + replies[16, 3] := "Are you disturbed by your dreams?"; + (* Hint: Automatically decomposed array initialization *) + replies[17, 0] := "How do you do ...please state your problem."; + (* Hint: Automatically decomposed array initialization *) + replies[18, 0] := "You don't seem quite certain."; + replies[18, 1] := "Why the uncertain tone?"; + replies[18, 2] := "Can't you be more positive?"; + replies[18, 3] := "You aren't sure?"; + replies[18, 4] := "Don't you know?"; + (* Hint: Automatically decomposed array initialization *) + replies[19, 0] := "Are you saying no just to be negative?"; + replies[19, 1] := "You are being a bit negative."; + replies[19, 2] := "Why not?"; + replies[19, 3] := "Are you sure?"; + replies[19, 4] := "Why no?"; + (* Hint: Automatically decomposed array initialization *) + replies[20, 0] := "Why are you concerned about my*?"; + replies[20, 1] := "What about your own*?"; + (* Hint: Automatically decomposed array initialization *) + replies[21, 0] := "Can you think of a specific example?"; + replies[21, 1] := "When?"; + replies[21, 2] := "What are you thinking of?"; + replies[21, 3] := "Really, always?"; + (* Hint: Automatically decomposed array initialization *) + replies[22, 0] := "Do you really think so?"; + replies[22, 1] := "But you are not sure you*?"; + replies[22, 2] := "Do you doubt you*?"; + (* Hint: Automatically decomposed array initialization *) + replies[23, 0] := "In what way?"; + replies[23, 1] := "What resemblance do you see?"; + replies[23, 2] := "What does the similarity suggest to you?"; + replies[23, 3] := "What other connections do you see?"; + replies[23, 4] := "Could there really be some connection?"; + replies[23, 5] := "How?"; + replies[23, 6] := "You seem quite positive."; + (* Hint: Automatically decomposed array initialization *) + replies[24, 0] := "Are you sure?"; + replies[24, 1] := "I see."; + replies[24, 2] := "I understand."; + (* Hint: Automatically decomposed array initialization *) + replies[25, 0] := "Why do you bring up the topic of friends?"; + replies[25, 1] := "Do your friends worry you?"; + replies[25, 2] := "Do your friends pick on you?"; + replies[25, 3] := "Are you sure you have any friends?"; + replies[25, 4] := "Do you impose on your friends?"; + replies[25, 5] := "Perhaps your love for friends worries you."; + (* Hint: Automatically decomposed array initialization *) + replies[26, 0] := "Do computers worry you?"; + replies[26, 1] := "Are you talking about me in particular?"; + replies[26, 2] := "Are you frightened by machines?"; + replies[26, 3] := "Why do you mention computers?"; + replies[26, 4] := "What do you think machines have to do with your problem?"; + replies[26, 5] := "Don't you think computers can help people?"; + replies[26, 6] := "What is it about machines that worries you?"; + (* Hint: Automatically decomposed array initialization *) + replies[27, 0] := "Do you sometimes feel uneasy without a smartphone?"; + replies[27, 1] := "Have you had these phantasies before?"; + replies[27, 2] := "Does the world seem more real for you via apps?"; + (* Hint: Automatically decomposed array initialization *) + replies[28, 0] := "Tell me more about your family."; + replies[28, 1] := "Who else in your family*?"; + replies[28, 2] := "What does family relations mean for you?"; + replies[28, 3] := "Come on, How old are you?"; + setupReplies := replies; + RETURN setupReplies; +END setupReplies; + +BEGIN + In.Open; + Out.Open; + (* histArray contains the most recent user replies as ring buffer; *) + (* histIndex is the index where the next reply is to be stored (= index of the oldest *) + (* cached user reply). *) + (* Note: The depth of the history is to be specified by initializing a variable of this type, *) + (* e.g. for a history of depth 5: *) + (* myhistory <- History{{"", "", "", "", ""}, 0} *) + (* Associates a key word in the text with an index in the reply ring array *) + (* Title information *) + Out.String("************* ELIZA **************"); + Out.Ln; + Out.String("* Original design by J. Weizenbaum"); + Out.Ln; + Out.String("**********************************"); + Out.Ln; + Out.String("* Adapted for Basic on IBM PC by"); + Out.Ln; + Out.String("* - Patricia Danielson"); + Out.Ln; + Out.String("* - Paul Hashfield"); + Out.Ln; + Out.String("**********************************"); + Out.Ln; + Out.String("* Adapted for Structorizer by"); + Out.Ln; + Out.String("* - Kay Gürtzig / FH Erfurt 2016"); + Out.Ln; + Out.String("* Version: 2.3 (2019-11-28)"); + Out.Ln; + Out.String("* (Requires at least Structorizer 3.30-03 to run)"); + Out.Ln; + Out.String("**********************************"); + Out.Ln; + (* Stores the last five inputs of the user in a ring buffer, *) + (* the second component is the rolling (over-)write index. *) + (* Hint: Automatically decomposed array initialization *) + history.histArray[0] := ""; + history.histArray[1] := ""; + history.histArray[2] := ""; + history.histArray[3] := ""; + history.histArray[4] := ""; + history.histIndex := 0; + replies := setupReplies(); + reflexions := setupReflexions(); + byePhrases := setupGoodByePhrases(); + keyMap := setupKeywords(); + offsets[length(keyMap)-1] := 0; + isGone := false; + (* Starter *) + Out.String("Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?"); + Out.Ln; + REPEAT + In.String(userInput); + (* Converts the input to lowercase, cuts out interpunctation *) + (* and pads the string *) + userInput := normalizeInput(userInput); + isGone := checkGoodBye(userInput, byePhrases); + IF ~ isGone THEN + reply := "Please don\'t repeat yourself!"; + isRepeated := checkRepetition(history, userInput); + IF ~ isRepeated THEN + findInfo := findKeyword(keyMap, userInput); + keyIndex := findInfo[0]; + IF keyIndex < 0 THEN + (* Should never happen... *) + keyIndex := length(keyMap)-1; + END; + entry := keyMap[keyIndex]; + (* Variable part of the reply *) + varPart := ""; + IF length(entry.keyword) > 0 THEN + varPart := conjugateStrings(userInput, entry.keyword, findInfo[1], reflexions); + END; + replyRing := replies[entry.index]; + reply := replyRing[offsets[keyIndex]]; + offsets[keyIndex] := (offsets[keyIndex] + 1) MOD length(replyRing); + posAster := pos("*", reply); + IF posAster > 0 THEN + IF varPart = " " THEN + reply := "You will have to elaborate more for me to help you."; + END + ELSE + delete(reply, posAster, 1); + insert(varPart, reply, posAster); + END; + END; + reply := adjustSpelling(reply); + END; + Out.String(reply); + Out.Ln; + END; + UNTIL isGone; +END ELIZA. diff --git a/samples/export/Oberon/SORTING_TEST_MAIN.Mod b/samples/export/Oberon/SORTING_TEST_MAIN.Mod index c5e58ea8..4aa5f8cf 100644 --- a/samples/export/Oberon/SORTING_TEST_MAIN.Mod +++ b/samples/export/Oberon/SORTING_TEST_MAIN.Mod @@ -1,4 +1,5 @@ MODULE SORTING_TEST_MAIN; +IMPORT dummy0815; IMPORT In, Out; (* * Creates three equal arrays of numbers and has them sorted with different sorting algorithms @@ -6,7 +7,7 @@ IMPORT In, Out; * sensibly be switched on). * Requested input data are: Number of elements (size) and filing mode. *) -(* Generated by Structorizer 3.30-02 *) +(* Generated by Structorizer 3.30-03 *) (* *) (* Copyright (C) 2019-10-02 Kay Gürtzig *) (* License: GPLv3-link *) @@ -16,17 +17,16 @@ IMPORT In, Out; (* *) VAR (* TODO: check and accomplish variable declarations *) - values3: ???; (* FIXME! *) - values2: ???; (* FIXME! *) - values1: ???; (* FIXME! *) + values3: ARRAY OF ???; (* FIXME! *) + values2: ARRAY OF ???; (* FIXME! *) + values1: ARRAY OF INTEGER; show: ???; (* FIXME! *) - ok3: ???; (* FIXME! *) - ok2: ???; (* FIXME! *) - ok1: ???; (* FIXME! *) + ok3: BOOLEAN; + ok2: BOOLEAN; + ok1: BOOLEAN; modus: ???; (* FIXME! *) i: INTEGER; elementCount: ???; (* FIXME! *) - [i]: ???; (* FIXME! *) PROCEDURE bubbleSort*(values: (*type?*)); (* @@ -283,7 +283,7 @@ BEGIN | END; END; - (* Kopiere das Array für exakte Vergleichbarkeit *) + (* Copy the array for exact comparability *) FOR i := 0 TO elementCount-1 DO values2[i] := values1[i]; values3[i] := values1[i]; diff --git a/samples/export/Oberon/TextDemo.Mod b/samples/export/Oberon/TextDemo.Mod new file mode 100644 index 00000000..edc9cd93 --- /dev/null +++ b/samples/export/Oberon/TextDemo.Mod @@ -0,0 +1,1296 @@ +MODULE TextDemo; +IMPORT dummy0815; +IMPORT In, Out; +(* + * Demo program for routine drawText() + * Asks the user to enter a text, a wanted text height and colour, + * and then draws this string onto the turtle screen. Places every + * entered text to a new line. + *) +(* Generated by Structorizer 3.30-03 *) +(* *) +(* Copyright (C) 2019-10-10 Kay Gürtzig *) +(* License: GPLv3-link *) +(* GNU General Public License (V 3) *) +(* https://www.gnu.org/licenses/gpl.html *) +(* http://www.gnu.de/documents/gpl.de.html *) +(* *) +VAR + (* TODO: check and accomplish variable declarations *) + y: INTEGER; + (* Make sure the content is interpreted as string *) + text: ???; (* FIXME! *) + height: ???; (* FIXME! *) + colour: ???; (* FIXME! *) + +PROCEDURE blank*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws a blank for font height h, ignoring the colorNo + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) +BEGIN + width := h/2.0; + penUp(); + right(90); + forward(width); (* color = ffffff *) + left(90); +END blank; + +PROCEDURE forward*(len: (*type?*); color: (*type?*)); +BEGIN + CASE color OF + 1: + forward(len); (* color = ffffff *) + | + 2: + forward(len); (* color = ff8080 *) + | + 3: + forward(len); (* color = ffff80 *) + | + 4: + forward(len); (* color = 80ff80 *) + | + 5: + forward(len); (* color = 80ffff *) + | + 6: + forward(len); (* color = 0080ff *) + | + 7: + forward(len); (* color = ff80c0 *) + | + 8: + forward(len); (* color = c0c0c0 *) + | + 9: + forward(len); (* color = ff8000 *) + | + 10: + forward(len); (* color = 8080ff *) + | + END; +END forward; + +PROCEDURE letterA*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter A in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: LONGREAL; +BEGIN + width := h/2.0; + hypo := sqrt(h*h + width*width/4.0); + rotAngle := toDegrees(atan(width/2.0/h)); + right(rotAngle); + forward(hypo/2.0, colorNo); + right(90 - rotAngle); + forward(width/2.0, colorNo); + penUp(); + backward(width/2.0); (* color = ffffff *) + penDown(); + left(90 - rotAngle); + forward(hypo/2.0, colorNo); + left(2*rotAngle); + forward(-hypo, colorNo); + right(rotAngle); +END letterA; + +PROCEDURE letterE*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter E in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) +BEGIN + width := h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); (* color = ffffff *) + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); (* color = ffffff *) + left(90); + penDown(); + forward(width, colorNo); + left(90); +END letterE; + +PROCEDURE letterF*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter F in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) +BEGIN + width := h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); (* color = ffffff *) + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); (* color = ffffff *) + left(90); + forward(width); (* color = ffffff *) + penDown(); + left(90); +END letterF; + +PROCEDURE letterH*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter H in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) +BEGIN + width := h/2.0; + forward(h, colorNo); + penUp(); + right(90); + forward(width); (* color = ffffff *) + right(90); + penDown(); + forward(h/2.0, colorNo); + right(90); + forward(width, colorNo); + penUp(); + backward(width); (* color = ffffff *) + left(90); + penDown(); + forward(h/2.0, colorNo); + left(180); +END letterH; + +PROCEDURE letterI*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter I in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* Cathetus of the corner triangle outside the octagon *) + c: ???; (* FIXME! *) + (* Octagon edge length *) + b: ???; (* FIXME! *) +BEGIN + (* Octagon edge length *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Cathetus of the corner triangle outside the octagon *) + c := b / sqrt(2.0); + penUp(); + right(90); + forward(c); (* color = ffffff *) + penDown(); + forward(b, colorNo); + penUp(); + backward(b/2.0); (* color = ffffff *) + left(90); + penDown(); + forward(h, colorNo); + penUp(); + right(90); + backward(b/2.0); (* color = ffffff *) + penDown(); + forward(b, colorNo); + penUp(); + forward(b/2 + c); (* color = ffffff *) + left(90); + backward(h); (* color = ffffff *) + penDown(); +END letterI; + +PROCEDURE letterK*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter K in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + diag: ???; (* FIXME! *) +BEGIN + width := h/2.0; + diag := h/sqrt(2.0); + forward(h, colorNo); + penUp(); + right(90); + forward(width); (* color = ffffff *) + right(135); + penDown(); + forward(diag, colorNo); + left(90); + forward(diag, colorNo); + left(135); +END letterK; + +PROCEDURE letterL*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter L in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) +BEGIN + width := h/2.0; + forward(h, colorNo); + penUp(); + backward(h); (* color = ffffff *) + right(90); + penDown(); + forward(width, colorNo); + left(90); +END letterL; + +PROCEDURE letterM*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter M in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: ???; (* FIXME! *) +BEGIN + width := h/2.0; + hypo := sqrt(width*width + h*h)/2.0; + rotAngle := toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + left(rotAngle); + forward(-h, colorNo); +END letterM; + +PROCEDURE letterN*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter N in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: LONGREAL; +BEGIN + width := h/2.0; + hypo := sqrt(width*width + h*h); + rotAngle := toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(rotAngle); + forward(h, colorNo); + penUp(); + backward(h); (* color = ffffff *) + penDown(); +END letterN; + +PROCEDURE letterT*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter T in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) +BEGIN + width := h/2.0; + penUp(); + forward(h); (* color = ffffff *) + penDown(); + right(90); + forward(width, colorNo); + penUp(); + backward(width/2.0); (* color = ffffff *) + penDown(); + right(90); + forward(h, colorNo); + left(90); + penUp(); + forward(width/2.0); (* color = ffffff *) + penDown(); + left(90); +END letterT; + +PROCEDURE letterV*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter V in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: LONGREAL; +BEGIN + width := h/2.0; + hypo := sqrt(h*h + width*width/4.0); + rotAngle := toDegrees(atan(width/2.0/h)); + penUp(); + forward(h); (* color = ffffff *) + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); (* color = ffffff *) + penDown(); +END letterV; + +PROCEDURE letterW*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter W in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width_3: ???; (* FIXME! *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: LONGREAL; +BEGIN + width := h/2.0; + width_3 := width/3.0; + hypo := sqrt(width_3*width_3 + h*h); + rotAngle := toDegrees(atan(width_3/h)); + penUp(); + forward(h); (* color = ffffff *) + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width_3); (* color = ffffff *) + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); (* color = ffffff *) + penDown(); +END letterW; + +PROCEDURE letterX*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter X in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: LONGREAL; +BEGIN + width := h/2.0; + hypo := sqrt(width*width + h*h); + rotAngle := toDegrees(atan(width/h)); + right(rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width); (* color = ffffff *) + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); +END letterX; + +PROCEDURE letterY*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter Y in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: ???; (* FIXME! *) +BEGIN + width := h/2.0; + hypo := sqrt(width*width + h*h)/2.0; + rotAngle := toDegrees(atan(width/h)); + penUp(); + forward(h); (* color = ffffff *) + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); + penUp(); + backward(h/2.0); (* color = ffffff *) + penDown(); + forward(h/2.0, colorNo); + right(rotAngle); + forward(hypo, colorNo); + left(rotAngle); + penUp(); + backward(h); (* color = ffffff *) + penDown(); +END letterY; + +PROCEDURE letterZ*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter Z in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle: LONGREAL; + hypo: LONGREAL; +BEGIN + width := h/2.0; + hypo := sqrt(width*width + h*h); + rotAngle := toDegrees(atan(width/h)); + penUp(); + forward(h); (* color = ffffff *) + right(90); + penDown(); + forward(width, colorNo); + left(90-rotAngle); + forward(-hypo, colorNo); + right(90-rotAngle); + forward(width, colorNo); + left(90); +END letterZ; + +PROCEDURE polygonPart*(a: LONGREAL; n: INTEGER; ctrclkws: BOOLEAN; nEdges, color: INTEGER); +(* + * Draws nEdges edges of a regular n-polygon with edge length a + * counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. + *) +VAR + (* TODO: check and accomplish variable declarations *) + rotAngle: ???; (* FIXME! *) + k: INTEGER; +BEGIN + rotAngle := 360.0/n; + IF ctrclkws THEN + rotAngle := -rotAngle; + END; + FOR k := 1 TO nEdges DO + right(rotAngle); + forward(a, color); + END; +END polygonPart; + +PROCEDURE charDummy*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws a dummy character (small centered square) with font height h and + * the colour encoded by colorNo + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + d: ???; (* FIXME! *) + (* Cathetus of the corner triangle outside the octagon *) + c: ???; (* FIXME! *) + (* Octagon edge length (here: edge lengzh of the square) *) + b: ???; (* FIXME! *) +BEGIN + width := h / 2.0; + (* Octagon edge length (here: edge lengzh of the square) *) + b := width / (sqrt(2.0) + 1); + (* Cathetus of the corner triangle outside the octagon *) + c := (width - b) / 2.0; + d := b / sqrt(2.0); + penUp(); + forward(h/2.0-b/2.0); (* color = ffffff *) + right(90); + forward(c); (* color = ffffff *) + right(90); + penDown(); + (* Draws the square with edge length b *) + polygonPart(b, 4, true, 4, colorNo); + penUp(); + left(90); + forward(b + c); (* color = ffffff *) + left(90); + backward(h/2.0-b/2.0); (* color = ffffff *) + penDown(); +END charDummy; + +PROCEDURE comma*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws a comma in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + rotAngle: LONGREAL; + hypo: ???; (* FIXME! *) + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + rotAngle := toDegrees(atan(0.5)); + hypo := c * sqrt(1.25); + penUp(); + right(90); + forward((c+b)/2.0 + c); (* color = ffffff *) + penDown(); + (* Counterclockwise draw 3 edges of a square with edge length c *) + (* in the colour endcoded by colorNo *) + polygonPart(c, 4, true, 3, colorNo); + left(90); + forward(c/2.0, colorNo); + right(90); + forward(c, colorNo); + left(180 - rotAngle); + forward(hypo, colorNo); + penUp(); + right(90 - rotAngle); + forward((c + b)/2.0); (* color = ffffff *) + left(90); + penDown(); +END comma; + +PROCEDURE exclMk*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws an exclamation mark in the colour encoded by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + width: ???; (* FIXME! *) + rotAngle2: LONGREAL; + (* 360°/8 *) + rotAngle: INTEGER; + length2: ???; (* FIXME! *) + length1: ???; (* FIXME! *) + hypo: LONGREAL; + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + width := h/2.0; + length1 := h - (b+c)/2.0; + length2 := length1 - 2*c; + hypo := sqrt(width*width/16.0 + length2*length2); + (* 360°/8 *) + rotAngle := 45; + rotAngle2 := toDegrees(atan(width/4.0/length2)); + penUp(); + forward(length1); (* color = ffffff *) + right(90); + forward(width/2.0); (* color = ffffff *) + left(90 + rotAngle); + penDown(); + (* Clockwise draw 5 edges of an octagon with edge length b/2 *) + (* in the colour endcoded by colorNo *) + polygonPart(b/2.0, 8, false, 5, colorNo); + right(rotAngle2); + forward(hypo, colorNo); + left(2*rotAngle2); + forward(-hypo, colorNo); + penUp(); + forward(hypo); (* color = ffffff *) + right(rotAngle2); + forward(c); (* color = ffffff *) + left(90); + forward(c/2.0); (* color = ffffff *) + penDown(); + (* Counterclockwise draw all 4 edges of a squarfe with edge length c *) + (* in the colour endcoded by colorNo *) + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); (* color = ffffff *) + left(90); + backward(c); (* color = ffffff *) + penDown(); +END exclMk; + +PROCEDURE fullSt*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws a full stop in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + penUp(); + right(90); + forward((c+b)/2.0 + c); (* color = ffffff *) + penDown(); + (* Counterclockwise draw all 4 edges of a squarfe with edge length c *) + (* in the colour endcoded by colorNo *) + polygonPart(c, 4, true, 4, colorNo); + penUp(); + forward((c + b)/2.0); (* color = ffffff *) + left(90); + penDown(); +END fullSt; + +PROCEDURE letterB*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter B in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* Cathetus of the outer corner triangle of the octagon *) + c: ???; (* FIXME! *) + (* Octagon edge length *) + b: ???; (* FIXME! *) +BEGIN + (* Octagon edge length *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Cathetus of the outer corner triangle of the octagon *) + c := b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + (* Clockwise draw 4 edges of an octagon with edge length b *) + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + c); (* color = ffffff *) + penDown(); + (* Clockwise draw 4 edges of an octagon with edge length b *) + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); (* color = ffffff *) + penDown(); + left(90); +END letterB; + +PROCEDURE letterC*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter C in the colour encoded by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* 360°/8 *) + rotAngle: INTEGER; + (* Cathetus of the outer trinagle at the octagon corner *) + c: ???; (* FIXME! *) + (* Octagon edge length *) + b: ???; (* FIXME! *) +BEGIN + (* Octagon edge length *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Cathetus of the outer trinagle at the octagon corner *) + c := b / sqrt(2.0); + (* 360°/8 *) + rotAngle := 45; + penUp(); + forward(c); (* color = ffffff *) + penDown(); + right(180); + (* Clockwise draws 3 edges of an octagon with edge length b in the colour *) + (* encoded by colorNo *) + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + penUp(); + forward(2*b + 2*c); (* color = ffffff *) + penDown(); + (* Counterclockwise draws 4 edges of an octagon with edge length b *) + (* iin the colour encoded by colorNo *) + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); (* color = ffffff *) + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); +END letterC; + +PROCEDURE letterD*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter D in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + (* Clockwise draw 2 edges of an octagon with edge length b in the colour *) + (* encoded by colorNo *) + polygonPart(b, 8, false, 2, colorNo); + forward(b + 2*c, colorNo); + (* Clockwise draw 2 edges of an octagon with edge length b in the colour *) + (* encoded by colorNo *) + polygonPart(b, 8, false, 2, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); (* color = ffffff *) + penDown(); + left(90); +END letterD; + +PROCEDURE letterG*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter G in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* Cathetus of the corner triangle outside the octagon. *) + c: ???; (* FIXME! *) + (* Octagon edge length *) + b: ???; (* FIXME! *) +BEGIN + (* Octagon edge length *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Cathetus of the corner triangle outside the octagon. *) + c := b / sqrt(2.0); + penUp(); + forward(c); (* color = ffffff *) + penDown(); + right(180); + (* Counterclockwise draw 4 edges of an octagon with edge length b in *) + (* the colour encoded by colorNo *) + polygonPart(b, 8, true, 4, colorNo); + forward(c, colorNo); + left(90); + forward(b/2.0 + c, colorNo); + penUp(); + backward(b/2.0 + c); (* color = ffffff *) + right(90); + forward(b + c); (* color = ffffff *) + penDown(); + (* Counterclockwise draw 4 edges of an octagon with edge length b in *) + (* the colour encoded by colorNo *) + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); (* color = ffffff *) + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); +END letterG; + +PROCEDURE letterJ*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter J in colour encoded by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* 360°/8 *) + rotAngle: INTEGER; + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + (* 360°/8 *) + rotAngle := 45; + penUp(); + forward(c); (* color = ffffff *) + penDown(); + right(180); + (* Counterclockwise draw 3 edges of an octagon with edge length b in *) + (* the colour encoded by colorNo *) + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); (* color = ffffff *) + penDown(); +END letterJ; + +PROCEDURE letterO*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter O in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* Cathetus of the corner triangle outside the octagon *) + c: ???; (* FIXME! *) + (* Octagon edge length *) + b: ???; (* FIXME! *) +BEGIN + (* Octagon edge length *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Cathetus of the corner triangle outside the octagon *) + c := b / sqrt(2.0); + penUp(); + forward(c); (* color = ffffff *) + penDown(); + right(180); + (* Counterclockwise draw 4 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + (* Counterclockwise draw 4 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); (* color = ffffff *) + left(90); + forward(b + 2*c); (* color = ffffff *) + penDown(); + left(90); +END letterO; + +PROCEDURE letterP*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter P in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* Cathetus of the corner triangle outside the octagon *) + c: ???; (* FIXME! *) + (* Octagon edge length *) + b: ???; (* FIXME! *) +BEGIN + (* Octagon edge length *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Cathetus of the corner triangle outside the octagon *) + c := b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + (* Clockwise draw 4 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + backward(b + 2*c); (* color = ffffff *) + left(90); + forward(b + 2*c); (* color = ffffff *) + penDown(); + left(180); +END letterP; + +PROCEDURE letterQ*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter Q in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* 360°/8 *) + rotAngle: INTEGER; + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + (* 360°/8 *) + rotAngle := 45; + penUp(); + forward(c); (* color = ffffff *) + penDown(); + right(180); + (* Counterclockwise draw 4 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + (* Counterclockwise draw 4 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); (* color = ffffff *) + left(90); + forward(b + 2*c); (* color = ffffff *) + right(rotAngle); + backward(b); (* color = ffffff *) + penDown(); + forward(b, colorNo); + left(90 + rotAngle); +END letterQ; + +PROCEDURE letterR*(h: (*type?*); colorNo: (*type?*)); +(* + * Zeichnet den Buchstaben R von der Turtleposition aus + * mit Zeilenhöhe h + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* 360°/8 *) + rotAngle: INTEGER; + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + (* 360°/8 *) + rotAngle := 45; + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + (* Clockwise draw 4 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + left(90 + rotAngle); + forward(sqrt(2.0)*(b + 2*c), colorNo); + left(90 + rotAngle); +END letterR; + +PROCEDURE letterS*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter S in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* 360°/8 *) + rotAngle: INTEGER; + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + (* 360°/8 *) + rotAngle := 45; + penUp(); + forward(c); (* color = ffffff *) + penDown(); + right(180); + (* Counterclockwise draw 6 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, true, 6, colorNo); + (* Clockwise draw 5 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, false, 5, colorNo); + right(rotAngle); + penUp(); + forward(2*b + 3*c); (* color = ffffff *) + penDown(); + left(180); +END letterS; + +PROCEDURE letterU*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws letter U in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* 360°/8 *) + rotAngle: INTEGER; + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* edge length of a regular octagon *) + b: ???; (* FIXME! *) +BEGIN + (* edge length of a regular octagon *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + (* 360°/8 *) + rotAngle := 45; + penUp(); + forward(c); (* color = ffffff *) + penDown(); + forward(h - c, colorNo); + penUp(); + backward(h-c); (* color = ffffff *) + penDown(); + right(180); + (* Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo *) + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); (* color = ffffff *) + penDown(); +END letterU; + +PROCEDURE qstnMk*(h: (*type?*); colorNo: (*type?*)); +(* + * Draws a question mark in colour specified by colorNo with font height h + * from the current turtle position. + *) +VAR + (* TODO: check and accomplish variable declarations *) + (* 360°/8 *) + rotAngle: INTEGER; + (* Eckenlänge außen am Achteck *) + c: ???; (* FIXME! *) + (* Achteck-Kantenlänge *) + b: ???; (* FIXME! *) +BEGIN + (* Achteck-Kantenlänge *) + b := h * 0.5 / (sqrt(2.0) + 1); + (* Eckenlänge außen am Achteck *) + c := b / sqrt(2.0); + (* 360°/8 *) + rotAngle := 45; + penUp(); + forward(h-c); (* color = ffffff *) + penDown(); + (* Counterclockwise draw 5 edges of an octagon with edge length b *) + (* in the colour endcoded by colorNo *) + polygonPart(b, 8, false, 5, colorNo); + forward(c, colorNo); + left(rotAngle); + forward(b/2.0, colorNo); + penUp(); + forward(c); (* color = ffffff *) + left(90); + forward(c/2.0); (* color = ffffff *) + penDown(); + (* Counterclockwise draw all 4 edges of a squarfe with edge length c *) + (* in the colour endcoded by colorNo *) + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); (* color = ffffff *) + left(90); + backward(c); (* color = ffffff *) + penDown(); +END qstnMk; + +PROCEDURE drawText*(text: ARRAY 100 OF CHAR; h, c: INTEGER); +(* + * Has the turtle draw the given string 'text´ with font height 'h´ (in + * pixels) and the colour coded by integer 'c´ from the current Turtle + * position to the Turtle canvas. If the turtle looks North then + * the text will be written rightwards. In the event, the turtle will be + * placed behind the text in original orientation (such that the next text + * would be written like a continuation. Colour codes: + * 1 = black + * 2 = red + * 3 = yellow + * 4 = green + * 5 = cyan + * 6 = blue + * 7 = pink + * 8 = grey + * 9 = orange + * 10 = violet + * All letters (ASCII) will be converted to uppercase, digits cannot + * be represented, the set of representable special characters is: + * '.', ',', '!', '?'. Other characters will be shown as a small + * centred square (dummy character). + *) +VAR + (* TODO: check and accomplish variable declarations *) + letter: ARRAY 100 OF CHAR; + k: INTEGER; + gap: ???; (* FIXME! *) +BEGIN + gap := h/10.0; + FOR k := 1 TO length(text) DO + letter := CAP(copy(text, k, 1)); + IF letter = "," THEN + comma(h,c); + END + ELSE + (* "," cannot be chacked against because the comma is misinterpreted *) + (* as selector list separator. *) + CASE letter OF + "A": + letterA(h,c); + | + "B": + letterB(h,c); + | + "C": + letterC(h,c); + | + "D": + letterD(h,c); + | + "E": + letterE(h,c); + | + "F": + letterF(h,c); + | + "G": + letterG(h,c); + | + "H": + letterH(h,c); + | + "I": + letterI(h,c); + | + "J": + letterJ(h,c); + | + "K": + letterK(h,c); + | + "L": + letterL(h,c); + | + "M": + letterM(h,c); + | + "N": + letterN(h,c); + | + "O": + letterO(h,c); + | + "P": + letterP(h,c); + | + "Q": + letterQ(h,c); + | + "R": + letterR(h,c); + | + "S": + letterS(h,c); + | + "T": + letterT(h,c); + | + "U": + letterU(h,c); + | + "V": + letterV(h,c); + | + "W": + letterW(h,c); + | + "X": + letterX(h,c); + | + "Y": + letterY(h,c); + | + "Z": + letterZ(h,c); + | + " ": + blank(h,c); + | + "!": + exclMk(h,c); + | + "?": + qstnMk(h,c); + | + ".": + fullSt(h,c); + | + ELSE + charDummy(h,c); + END; + END; + right(90); + penUp(); + forward(gap); (* color = ffffff *) + penDown(); + left(90); + END; +END drawText; + +BEGIN + In.Open; + Out.Open; + Out.String("This is a demo program for text writing with Turleizer."); + Out.Ln; + showTurtle(); + penDown(); + y := 0; + REPEAT + (* TODO: Replace "TYPE" by the the actual In procedure name for this type! *) + Out.String("Enter some text (empty string to exit)"); In.TYPE(text); + (* Make sure the content is interpreted as string *) + text := "" + text; + IF text # "" THEN + REPEAT + (* TODO: Replace "TYPE" by the the actual In procedure name for this type! *) + Out.String("Height of the text (pixels)"); In.TYPE(height); + UNTIL height >= 5; + REPEAT + (* TODO: Replace "TYPE" by the the actual In procedure name for this type! *) + Out.String("Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"); In.TYPE(colour); + UNTIL colour >= 1 & colour <= 10; + y := y + height + 2; + gotoXY(0, y - 2); + drawText(text, height, colour); + END; + UNTIL text = ""; + gotoXY(0, y + 15); + drawText("Thank you, bye.", 10, 4); + hideTurtle(); +END TextDemo. diff --git a/samples/export/PHP/ELIZA_2.3.php b/samples/export/PHP/ELIZA_2.3.php new file mode 100644 index 00000000..f3e7691c --- /dev/null +++ b/samples/export/PHP/ELIZA_2.3.php @@ -0,0 +1,406 @@ + 0) + { + delete($result, $position+1, 1); + insert("I", $result, $position+1); + $position = pos($word, $result); + } + } + + return $result; +} + +// function checkGoodBye +// Checks whether the given text contains some kind of +// good-bye phrase inducing the end of the conversation +// and if so writes a correspding good-bye message and +// returns true, otherwise false +function checkGoodBye($text, $phrases) +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + foreach ($phrases as $pair) + { + if (pos($pair[0], $text) > 0) + { + $saidBye = true; + echo $pair[1]; + return true; + } + } + return false; +} + +// function checkRepetition +// Checks whether newInput has occurred among the recently cached +// input strings in the histArray component of history and updates the history. +function checkRepetition($history, $newInput) +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + $hasOccurred = false; + if (length($newInput) > 4) + { + $histDepth = length($history.histArray); + for ($i = 0; $i <= $histDepth-1; $i += (1)) + { + if ($newInput == $history.histArray[$i]) + { + $hasOccurred = true; + } + } + $history.histArray[$history.histIndex] = $newInput; + $history.histIndex = ($history.histIndex + 1) % ($histDepth); + } + return $hasOccurred; +} + +// function conjugateStrings +function conjugateStrings($sentence, $key, $keyPos, $flexions) +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + $result = " " + copy($sentence, $keyPos + length($key), length($sentence)) + " "; + foreach ($flexions as $pair) + { + $left = ""; + $right = $result; + $position = pos($pair[0], $right); + while ($position > 0) + { + $left = $left + copy($right, 1, $position-1) + $pair[1]; + $right = copy($right, $position + length($pair[0]), length($right)); + $position = pos($pair[0], $right); + } + $result = $left + $right; + } + // Eliminate multiple spaces + $position = pos(" ", $result); + while ($position > 0) + { + $result = copy($result, 1, $position-1) + copy($result, $position+1, length($result)); + $position = pos(" ", $result); + } + + return $result; +} + +// function findKeyword +// Looks for the occurrence of the first of the strings +// contained in keywords within the given sentence (in +// array order). +// Returns an array of +// 0: the index of the first identified keyword (if any, otherwise -1), +// 1: the position inside sentence (0 if not found) +function findKeyword($keyMap, $sentence) +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + // Contains the index of the keyword and its position in sentence + $result = {-1, 0}; + $i = 0; + while (($result[0] < 0) && ($i < length($keyMap))) + { + var $entry: KeyMapEntry = $keyMap[$i]; + $position = pos($entry.keyword, $sentence); + if ($position > 0) + { + $result[0] = $i; + $result[1] = $position; + } + $i = $i+1; + } + + return $result; +} + +// function normalizeInput +// Converts the sentence to lowercase, eliminates all +// interpunction (i.e. ',', '.', ';'), and pads the +// sentence among blanks +function normalizeInput($sentence) +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + $sentence = lowercase($sentence); + foreach (array('.', ',', ';', '!', '?') as $symbol) + { + $position = pos($symbol, $sentence); + while ($position > 0) + { + $sentence = copy($sentence, 1, $position-1) + copy($sentence, $position+1, length($sentence)); + $position = pos($symbol, $sentence); + } + } + $result = " " + $sentence + " "; + + return $result; +} + +// function setupGoodByePhrases +function setupGoodByePhrases() +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + $phrases[0] = {" shut", "Okay. If you feel that way I\'ll shut up. ... Your choice."}; + $phrases[1] = {"bye", "Well, let\'s end our talk for now. See you later. Bye."}; + return $phrases; +} + +// function setupKeywords +// The lower the index the higher the rank of the keyword (search is sequential). +// The index of the first keyword found in a user sentence maps to a respective +// reply ring as defined in `setupReplies()´. +function setupKeywords() +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + // The empty key string (last entry) is the default clause - will always be found + $keywords[39] = KeyMapEntry{"", 29}; + $keywords[0] = KeyMapEntry{"can you ", 0}; + $keywords[1] = KeyMapEntry{"can i ", 1}; + $keywords[2] = KeyMapEntry{"you are ", 2}; + $keywords[3] = KeyMapEntry{"you\'re ", 2}; + $keywords[4] = KeyMapEntry{"i don't ", 3}; + $keywords[5] = KeyMapEntry{"i feel ", 4}; + $keywords[6] = KeyMapEntry{"why don\'t you ", 5}; + $keywords[7] = KeyMapEntry{"why can\'t i ", 6}; + $keywords[8] = KeyMapEntry{"are you ", 7}; + $keywords[9] = KeyMapEntry{"i can\'t ", 8}; + $keywords[10] = KeyMapEntry{"i am ", 9}; + $keywords[11] = KeyMapEntry{"i\'m ", 9}; + $keywords[12] = KeyMapEntry{"you ", 10}; + $keywords[13] = KeyMapEntry{"i want ", 11}; + $keywords[14] = KeyMapEntry{"what ", 12}; + $keywords[15] = KeyMapEntry{"how ", 12}; + $keywords[16] = KeyMapEntry{"who ", 12}; + $keywords[17] = KeyMapEntry{"where ", 12}; + $keywords[18] = KeyMapEntry{"when ", 12}; + $keywords[19] = KeyMapEntry{"why ", 12}; + $keywords[20] = KeyMapEntry{"name ", 13}; + $keywords[21] = KeyMapEntry{"cause ", 14}; + $keywords[22] = KeyMapEntry{"sorry ", 15}; + $keywords[23] = KeyMapEntry{"dream ", 16}; + $keywords[24] = KeyMapEntry{"hello ", 17}; + $keywords[25] = KeyMapEntry{"hi ", 17}; + $keywords[26] = KeyMapEntry{"maybe ", 18}; + $keywords[27] = KeyMapEntry{" no", 19}; + $keywords[28] = KeyMapEntry{"your ", 20}; + $keywords[29] = KeyMapEntry{"always ", 21}; + $keywords[30] = KeyMapEntry{"think ", 22}; + $keywords[31] = KeyMapEntry{"alike ", 23}; + $keywords[32] = KeyMapEntry{"yes ", 24}; + $keywords[33] = KeyMapEntry{"friend ", 25}; + $keywords[34] = KeyMapEntry{"computer", 26}; + $keywords[35] = KeyMapEntry{"bot ", 26}; + $keywords[36] = KeyMapEntry{"smartphone", 27}; + $keywords[37] = KeyMapEntry{"father ", 28}; + $keywords[38] = KeyMapEntry{"mother ", 28}; + return $keywords; +} + +// function setupReflexions +// Returns an array of pairs of mutualy substitutable +function setupReflexions() +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + $reflexions[0] = {" are ", " am "}; + $reflexions[1] = {" were ", " was "}; + $reflexions[2] = {" you ", " I "}; + $reflexions[3] = {" your", " my"}; + $reflexions[4] = {" i\'ve ", " you\'ve "}; + $reflexions[5] = {" i\'m ", " you\'re "}; + $reflexions[6] = {" me ", " you "}; + $reflexions[7] = {" my ", " your "}; + $reflexions[8] = {" i ", " you "}; + $reflexions[9] = {" am ", " are "}; + return $reflexions; +} + +// function setupReplies +// This routine sets up the reply rings addressed by the key words defined in +// routine `setupKeywords()´ and mapped hitherto by the cross table defined +// in `setupMapping()´ +function setupReplies() +{ + // TODO declare your variables here if necessary + + // TODO Establish sensible web formulars to get the $_GET input working. + + var $replies: array of array of String; + // We start with the highest index for performance reasons + // (is to avoid frequent array resizing) + $replies[29] = { "Say, do you have any psychological problems?", "What does that suggest to you?", "I see.", "I'm not sure I understand you fully.", "Come come elucidate your thoughts.", "Can you elaborate on that?", "That is quite interesting."}; + $replies[0] = { "Don't you believe that I can*?", "Perhaps you would like to be like me?", "You want me to be able to*?"}; + $replies[1] = { "Perhaps you don't want to*?", "Do you want to be able to*?"}; + $replies[2] = { "What makes you think I am*?", "Does it please you to believe I am*?", "Perhaps you would like to be*?", "Do you sometimes wish you were*?"}; + $replies[3] = { "Don't you really*?", "Why don't you*?", "Do you wish to be able to*?", "Does that trouble you*?"}; + $replies[4] = { "Do you often feel*?", "Are you afraid of feeling*?", "Do you enjoy feeling*?"}; + $replies[5] = { "Do you really believe I don't*?", "Perhaps in good time I will*.", "Do you want me to*?"}; + $replies[6] = { "Do you think you should be able to*?", "Why can't you*?"}; + $replies[7] = { "Why are you interested in whether or not I am*?", "Would you prefer if I were not*?", "Perhaps in your fantasies I am*?"}; + $replies[8] = { "How do you know you can't*?", "Have you tried?","Perhaps you can now*."}; + $replies[9] = { "Did you come to me because you are*?", "How long have you been*?", "Do you believe it is normal to be*?", "Do you enjoy being*?"}; + $replies[10] = { "We were discussing you--not me.", "Oh, I*.", "You're not really talking about me, are you?"}; + $replies[11] = { "What would it mean to you if you got*?", "Why do you want*?", "Suppose you soon got*...", "What if you never got*?", "I sometimes also want*."}; + $replies[12] = { "Why do you ask?", "Does that question interest you?", "What answer would please you the most?", "What do you think?", "Are such questions on your mind often?", "What is it that you really want to know?", "Have you asked anyone else?", "Have you asked such questions before?", "What else comes to mind when you ask that?"}; + $replies[13] = { "Names don't interest me.", "I don't care about names -- please go on."}; + $replies[14] = { "Is that the real reason?", "Don't any other reasons come to mind?", "Does that reason explain anything else?", "What other reasons might there be?"}; + $replies[15] = { "Please don't apologize!", "Apologies are not necessary.", "What feelings do you have when you apologize?", "Don't be so defensive!"}; + $replies[16] = { "What does that dream suggest to you?", "Do you dream often?", "What persons appear in your dreams?", "Are you disturbed by your dreams?"}; + $replies[17] = { "How do you do ...please state your problem."}; + $replies[18] = { "You don't seem quite certain.", "Why the uncertain tone?", "Can't you be more positive?", "You aren't sure?", "Don't you know?"}; + $replies[19] = { "Are you saying no just to be negative?", "You are being a bit negative.", "Why not?", "Are you sure?", "Why no?"}; + $replies[20] = { "Why are you concerned about my*?", "What about your own*?"}; + $replies[21] = { "Can you think of a specific example?", "When?", "What are you thinking of?", "Really, always?"}; + $replies[22] = { "Do you really think so?", "But you are not sure you*?", "Do you doubt you*?"}; + $replies[23] = { "In what way?", "What resemblance do you see?", "What does the similarity suggest to you?", "What other connections do you see?", "Could there really be some connection?", "How?", "You seem quite positive."}; + $replies[24] = { "Are you sure?", "I see.", "I understand."}; + $replies[25] = { "Why do you bring up the topic of friends?", "Do your friends worry you?", "Do your friends pick on you?", "Are you sure you have any friends?", "Do you impose on your friends?", "Perhaps your love for friends worries you."}; + $replies[26] = { "Do computers worry you?", "Are you talking about me in particular?", "Are you frightened by machines?", "Why do you mention computers?", "What do you think machines have to do with your problem?", "Don't you think computers can help people?", "What is it about machines that worries you?"}; + $replies[27] = { "Do you sometimes feel uneasy without a smartphone?", "Have you had these phantasies before?", "Does the world seem more real for you via apps?"}; + $replies[28] = { "Tell me more about your family.", "Who else in your family*?", "What does family relations mean for you?", "Come on, How old are you?"}; + $setupReplies = $replies; + + return $setupReplies; +} + +// program ELIZA +// Concept and lisp implementation published by Joseph Weizenbaum (MIT): +// "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +// Computational Linguistis 1(1966)9, pp. 36-45 +// Revision history: +// 2016-10-06 Initial version +// 2017-03-29 Two diagrams updated (comments translated to English) +// 2017-03-29 More keywords and replies added +// 2019-03-14 Replies and mapping reorganised for easier maintenance +// 2019-03-15 key map joined from keyword array and index map +// 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +// 2019-11-28 New global type "History" (to ensure a homogenous array) + +// TODO declare your variables here if necessary + +// TODO Establish sensible web formulars to get the $_GET input working. + +// Title information +echo "************* ELIZA **************"; +echo "* Original design by J. Weizenbaum"; +echo "**********************************"; +echo "* Adapted for Basic on IBM PC by"; +echo "* - Patricia Danielson"; +echo "* - Paul Hashfield"; +echo "**********************************"; +echo "* Adapted for Structorizer by"; +echo "* - Kay Gürtzig / FH Erfurt 2016"; +echo "* Version: 2.3 (2019-11-28)"; +echo "* (Requires at least Structorizer 3.30-03 to run)"; +echo "**********************************"; +// Stores the last five inputs of the user in a ring buffer, +// the second component is the rolling (over-)write index. +$history = History{{"", "", "", "", ""}, 0}; +const $replies = setupReplies(); +const $reflexions = setupReflexions(); +const $byePhrases = setupGoodByePhrases(); +const $keyMap = setupKeywords(); +$offsets[length($keyMap)-1] = 0; +$isGone = false; +// Starter +echo "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?"; +do +{ + $userInput = $_REQUEST['userInput']; // TODO form a sensible input opportunity; + // Converts the input to lowercase, cuts out interpunctation + // and pads the string + $userInput = normalizeInput($userInput); + $isGone = checkGoodBye($userInput, $byePhrases); + if (! $isGone) + { + $reply = "Please don\'t repeat yourself!"; + $isRepeated = checkRepetition($history, $userInput); + if (! $isRepeated) + { + $findInfo = findKeyword($keyMap, $userInput); + $keyIndex = $findInfo[0]; + if ($keyIndex < 0) + { + // Should never happen... + $keyIndex = length($keyMap)-1; + } + var $entry: KeyMapEntry = $keyMap[$keyIndex]; + // Variable part of the reply + $varPart = ""; + if (length($entry.keyword) > 0) + { + $varPart = conjugateStrings($userInput, $entry.keyword, $findInfo[1], $reflexions); + } + $replyRing = $replies[$entry.index]; + $reply = $replyRing[$offsets[$keyIndex]]; + $offsets[$keyIndex] = ($offsets[$keyIndex] + 1) % length($replyRing); + $posAster = pos("*", $reply); + if ($posAster > 0) + { + if ($varPart == " ") + { + $reply = "You will have to elaborate more for me to help you."; + } + else + { + delete($reply, $posAster, 1); + insert($varPart, $reply, $posAster); + } + } + $reply = adjustSpelling($reply); + } + echo $reply; + } +} while (!( $isGone )); +?> diff --git a/samples/export/PHP/SORTING_TEST_MAIN.php b/samples/export/PHP/SORTING_TEST_MAIN.php index d1801599..0f363a3e 100644 --- a/samples/export/PHP/SORTING_TEST_MAIN.php +++ b/samples/export/PHP/SORTING_TEST_MAIN.php @@ -1,5 +1,5 @@ = 5 )); + do + { + $colour = $_REQUEST["Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"]; // TODO form a sensible input opportunity; + } while (!( $colour >= 1 && $colour <= 10 )); + $y = $y + $height + 2; + gotoXY(0, $y - 2); + drawText($text, $height, $colour); + } +} while (!( $text == "" )); +gotoXY(0, $y + 15); +drawText("Thank you, bye.", 10, 4); +hideTurtle(); +?> diff --git a/samples/export/Pascal/ELIZA_2.3.pas b/samples/export/Pascal/ELIZA_2.3.pas new file mode 100644 index 00000000..c7e7f3da --- /dev/null +++ b/samples/export/Pascal/ELIZA_2.3.pas @@ -0,0 +1,673 @@ +{ Concept and lisp implementation published by Joseph Weizenbaum (MIT): } +{ "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: } +{ Computational Linguistis 1(1966)9, pp. 36-45 } +{ Revision history: } +{ 2016-10-06 Initial version } +{ 2017-03-29 Two diagrams updated (comments translated to English) } +{ 2017-03-29 More keywords and replies added } +{ 2019-03-14 Replies and mapping reorganised for easier maintenance } +{ 2019-03-15 key map joined from keyword array and index map } +{ 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") } +{ 2019-11-28 New global type "History" (to ensure a homogenous array) } +{ Generated by Structorizer 3.30-03 } +{ } +{ Copyright (C) 2018-05-14 Kay Gürtzig } +{ License: GPLv3-link } +{ GNU General Public License (V 3) } +{ https://www.gnu.org/licenses/gpl.html } +{ http://www.gnu.de/documents/gpl.de.html } +{ } +program ELIZA; + + +type + { histArray contains the most recent user replies as ring buffer; } + { histIndex is the index where the next reply is to be stored (= index of the oldest } + { cached user reply). } + { Note: The depth of the history is to be specified by initializing a variable of this type, } + { e.g. for a history of depth 5: } + { myhistory <- History{{"", "", "", "", ""}, 0} } + History = RECORD + histArray: array of string; + histIndex: Longint; + END; + + { Associates a key word in the text with an index in the reply ring array } + KeyMapEntry = RECORD + keyword: string; + index: Longint; + END; + +const + replies = setupReplies(); + + reflexions = setupReflexions(); + + byePhrases = setupGoodByePhrases(); + + keyMap = setupKeywords(); + +var + index29f23747: 1..5; + array29f23747: array [1..5] of string; + index7507a2dd: 1..2; + array7507a2dd: array [1..2] of string; + varPart: String; + { Converts the input to lowercase, cuts out interpunctation } + { and pads the string } + userInput: string; + replyRing: ???; { FIXME! } + reply: String; + posAster: Longint; + offsets: array of Longint; + { Should never happen... } + keyIndex: ???; { FIXME! } + isRepeated: boolean; + isGone: boolean; + { Stores the last five inputs of the user in a ring buffer, } + { the second component is the rolling (over-)write index. } + history: History; + findInfo: array [0..1] of Longint; + entry: KeyMapEntry; + + +{ Cares for correct letter case among others } +function adjustSpelling(sentence: string): string; + +var + word: String; + start: string; + result: string; + position: Longint; + +begin + result := sentence; + position := 1; + while (position <= length(sentence)) and (copy(sentence, position, 1) = ' ') do + begin + position := position + 1; + end; + if position <= length(sentence) then + begin + start := copy(sentence, 1, position); + delete(result, 1, position); + insert(uppercase(start), result, 1); + end; + array7507a2dd[1] := ' i '; + array7507a2dd[2] := ' i\'''; + for index7507a2dd := 1 to 2 do + begin + word := array7507a2dd[index7507a2dd]; + position := pos(word, result); + while (position > 0) do + begin + delete(result, position+1, 1); + insert('I', result, position+1); + position := pos(word, result); + end; + end; + +{ Automatically inserted to ensure Pascal value return. May be dropped on Structorizer reimport. } + adjustSpelling := result; + +end; + +{ Checks whether the given text contains some kind of } +{ good-bye phrase inducing the end of the conversation } +{ and if so writes a correspding good-bye message and } +{ returns true, otherwise false } +function checkGoodBye(text: string; phrases: array of array [0..1] of string): boolean; + +var + saidBye: boolean; + pair: array of string; + +begin + { TODO: Rewrite this loop (there was no way to convert this automatically) } + for pair in phrases do + begin + if (pos(pair[0], text) > 0) then + begin + saidBye := true; + writeln(pair[1]); + checkGoodBye := true; + exit; + end; + end; + checkGoodBye := false; + +end; + +{ Checks whether newInput has occurred among the recently cached } +{ input strings in the histArray component of history and updates the history. } +function checkRepetition(history: History; newInput: string): boolean; + +var + i: Longint; + histDepth: Longint; + hasOccurred: boolean; + +begin + hasOccurred := false; + if (length(newInput) > 4) then + begin + histDepth := length(history.histArray); + for i := 0 to histDepth-1 do + begin + if (newInput = history.histArray[i]) then + begin + hasOccurred := true; + end; + end; + history.histArray[history.histIndex] := newInput; + history.histIndex := (history.histIndex + 1) mod (histDepth); + end; + checkRepetition := hasOccurred; + +end; + +function conjugateStrings(sentence: string; key: string; keyPos: Longint; flexions: array of array [0..1] of string): string; + +var + right: String; + result: String; + position: Longint; + pair: array of string; + left: String; + +begin + result := ' ' + copy(sentence, keyPos + length(key), length(sentence)) + ' '; + { TODO: Rewrite this loop (there was no way to convert this automatically) } + for pair in flexions do + begin + left := ''; + right := result; + position := pos(pair[0], right); + while (position > 0) do + begin + left := left + copy(right, 1, position-1) + pair[1]; + right := copy(right, position + length(pair[0]), length(right)); + position := pos(pair[0], right); + end; + result := left + right; + end; + { Eliminate multiple spaces } + position := pos(' ', result); + while (position > 0) do + begin + result := copy(result, 1, position-1) + copy(result, position+1, length(result)); + position := pos(' ', result); + end; + +{ Automatically inserted to ensure Pascal value return. May be dropped on Structorizer reimport. } + conjugateStrings := result; + +end; + +{ Looks for the occurrence of the first of the strings } +{ contained in keywords within the given sentence (in } +{ array order). } +{ Returns an array of } +{ 0: the index of the first identified keyword (if any, otherwise -1), } +{ 1: the position inside sentence (0 if not found) } +function findKeyword(keyMap: const array of KeyMapEntry; sentence: string): array [0..1] of Longint; + +const + keyMap = null; + +var + result: array [0..1] of Longint; + position: Longint; + i: Longint; + entry: KeyMapEntry; + +begin + { Contains the index of the keyword and its position in sentence } + { Hint: Automatically decomposed array initialization } + result[0] := -1; + result[1] := 0; + i := 0; + while (result[0] < 0) and (i < length(keyMap)) do + begin + entry := keyMap[i]; + position := pos(entry.keyword, sentence); + if (position > 0) then + begin + result[0] := i; + result[1] := position; + end; + i := i+1; + end; + +{ Automatically inserted to ensure Pascal value return. May be dropped on Structorizer reimport. } + findKeyword := result; + +end; + +{ Converts the sentence to lowercase, eliminates all } +{ interpunction (i.e. ',', '.', ';'), and pads the } +{ sentence among blanks } +function normalizeInput(sentence: string): string; + +var + symbol: String; + result: String; + position: Longint; + +begin + sentence := lowercase(sentence); + array29f23747[1] := '.'; + array29f23747[2] := ','; + array29f23747[3] := ';'; + array29f23747[4] := '!'; + array29f23747[5] := '?'; + for index29f23747 := 1 to 5 do + begin + symbol := array29f23747[index29f23747]; + position := pos(symbol, sentence); + while (position > 0) do + begin + sentence := copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)); + position := pos(symbol, sentence); + end; + end; + result := ' ' + sentence + ' '; + +{ Automatically inserted to ensure Pascal value return. May be dropped on Structorizer reimport. } + normalizeInput := result; + +end; + +function setupGoodByePhrases(): array of array [0..1] of string; + +var + phrases: array of array [0..1] of String; + +begin + { Hint: Automatically decomposed array initialization } + phrases[0, 0] := ' shut'; + phrases[0, 1] := 'Okay. If you feel that way I\''ll shut up. ... Your choice.'; + { Hint: Automatically decomposed array initialization } + phrases[1, 0] := 'bye'; + phrases[1, 1] := 'Well, let\''s end our talk for now. See you later. Bye.'; + setupGoodByePhrases := phrases; + +end; + +{ The lower the index the higher the rank of the keyword (search is sequential). } +{ The index of the first keyword found in a user sentence maps to a respective } +{ reply ring as defined in `setupReplies()´. } +function setupKeywords(): array of KeyMapEntry; + +var + { The empty key string (last entry) is the default clause - will always be found } + keywords: array of KeyMapEntry; + +begin + { The empty key string (last entry) is the default clause - will always be found } + keywords[39].keyword := ''; + keywords[39].index := 29; + keywords[0].keyword := 'can you '; + keywords[0].index := 0; + keywords[1].keyword := 'can i '; + keywords[1].index := 1; + keywords[2].keyword := 'you are '; + keywords[2].index := 2; + keywords[3].keyword := 'you\''re '; + keywords[3].index := 2; + keywords[4].keyword := 'i don''t '; + keywords[4].index := 3; + keywords[5].keyword := 'i feel '; + keywords[5].index := 4; + keywords[6].keyword := 'why don\''t you '; + keywords[6].index := 5; + keywords[7].keyword := 'why can\''t i '; + keywords[7].index := 6; + keywords[8].keyword := 'are you '; + keywords[8].index := 7; + keywords[9].keyword := 'i can\''t '; + keywords[9].index := 8; + keywords[10].keyword := 'i am '; + keywords[10].index := 9; + keywords[11].keyword := 'i\''m '; + keywords[11].index := 9; + keywords[12].keyword := 'you '; + keywords[12].index := 10; + keywords[13].keyword := 'i want '; + keywords[13].index := 11; + keywords[14].keyword := 'what '; + keywords[14].index := 12; + keywords[15].keyword := 'how '; + keywords[15].index := 12; + keywords[16].keyword := 'who '; + keywords[16].index := 12; + keywords[17].keyword := 'where '; + keywords[17].index := 12; + keywords[18].keyword := 'when '; + keywords[18].index := 12; + keywords[19].keyword := 'why '; + keywords[19].index := 12; + keywords[20].keyword := 'name '; + keywords[20].index := 13; + keywords[21].keyword := 'cause '; + keywords[21].index := 14; + keywords[22].keyword := 'sorry '; + keywords[22].index := 15; + keywords[23].keyword := 'dream '; + keywords[23].index := 16; + keywords[24].keyword := 'hello '; + keywords[24].index := 17; + keywords[25].keyword := 'hi '; + keywords[25].index := 17; + keywords[26].keyword := 'maybe '; + keywords[26].index := 18; + keywords[27].keyword := ' no'; + keywords[27].index := 19; + keywords[28].keyword := 'your '; + keywords[28].index := 20; + keywords[29].keyword := 'always '; + keywords[29].index := 21; + keywords[30].keyword := 'think '; + keywords[30].index := 22; + keywords[31].keyword := 'alike '; + keywords[31].index := 23; + keywords[32].keyword := 'yes '; + keywords[32].index := 24; + keywords[33].keyword := 'friend '; + keywords[33].index := 25; + keywords[34].keyword := 'computer'; + keywords[34].index := 26; + keywords[35].keyword := 'bot '; + keywords[35].index := 26; + keywords[36].keyword := 'smartphone'; + keywords[36].index := 27; + keywords[37].keyword := 'father '; + keywords[37].index := 28; + keywords[38].keyword := 'mother '; + keywords[38].index := 28; + setupKeywords := keywords; + +end; + +{ Returns an array of pairs of mutualy substitutable } +function setupReflexions(): array of array [0..1] of string; + +var + reflexions: array of array [0..1] of String; + +begin + { Hint: Automatically decomposed array initialization } + reflexions[0, 0] := ' are '; + reflexions[0, 1] := ' am '; + { Hint: Automatically decomposed array initialization } + reflexions[1, 0] := ' were '; + reflexions[1, 1] := ' was '; + { Hint: Automatically decomposed array initialization } + reflexions[2, 0] := ' you '; + reflexions[2, 1] := ' I '; + { Hint: Automatically decomposed array initialization } + reflexions[3, 0] := ' your'; + reflexions[3, 1] := ' my'; + { Hint: Automatically decomposed array initialization } + reflexions[4, 0] := ' i\''ve ', ' you\''ve '; + { Hint: Automatically decomposed array initialization } + reflexions[5, 0] := ' i\''m ', ' you\''re '; + { Hint: Automatically decomposed array initialization } + reflexions[6, 0] := ' me '; + reflexions[6, 1] := ' you '; + { Hint: Automatically decomposed array initialization } + reflexions[7, 0] := ' my '; + reflexions[7, 1] := ' your '; + { Hint: Automatically decomposed array initialization } + reflexions[8, 0] := ' i '; + reflexions[8, 1] := ' you '; + { Hint: Automatically decomposed array initialization } + reflexions[9, 0] := ' am '; + reflexions[9, 1] := ' are '; + setupReflexions := reflexions; + +end; + +{ This routine sets up the reply rings addressed by the key words defined in } +{ routine `setupKeywords()´ and mapped hitherto by the cross table defined } +{ in `setupMapping()´ } +function setupReplies(): array of array of string; + +var + replies: array of array of String; + +begin + { We start with the highest index for performance reasons } + { (is to avoid frequent array resizing) } + { Hint: Automatically decomposed array initialization } + replies[29, 0] := 'Say, do you have any psychological problems?'; + replies[29, 1] := 'What does that suggest to you?'; + replies[29, 2] := 'I see.'; + replies[29, 3] := 'I''m not sure I understand you fully.'; + replies[29, 4] := 'Come come elucidate your thoughts.'; + replies[29, 5] := 'Can you elaborate on that?'; + replies[29, 6] := 'That is quite interesting.'; + { Hint: Automatically decomposed array initialization } + replies[0, 0] := 'Don''t you believe that I can*?'; + replies[0, 1] := 'Perhaps you would like to be like me?'; + replies[0, 2] := 'You want me to be able to*?'; + { Hint: Automatically decomposed array initialization } + replies[1, 0] := 'Perhaps you don''t want to*?'; + replies[1, 1] := 'Do you want to be able to*?'; + { Hint: Automatically decomposed array initialization } + replies[2, 0] := 'What makes you think I am*?'; + replies[2, 1] := 'Does it please you to believe I am*?'; + replies[2, 2] := 'Perhaps you would like to be*?'; + replies[2, 3] := 'Do you sometimes wish you were*?'; + { Hint: Automatically decomposed array initialization } + replies[3, 0] := 'Don''t you really*?'; + replies[3, 1] := 'Why don''t you*?'; + replies[3, 2] := 'Do you wish to be able to*?'; + replies[3, 3] := 'Does that trouble you*?'; + { Hint: Automatically decomposed array initialization } + replies[4, 0] := 'Do you often feel*?'; + replies[4, 1] := 'Are you afraid of feeling*?'; + replies[4, 2] := 'Do you enjoy feeling*?'; + { Hint: Automatically decomposed array initialization } + replies[5, 0] := 'Do you really believe I don''t*?'; + replies[5, 1] := 'Perhaps in good time I will*.'; + replies[5, 2] := 'Do you want me to*?'; + { Hint: Automatically decomposed array initialization } + replies[6, 0] := 'Do you think you should be able to*?'; + replies[6, 1] := 'Why can''t you*?'; + { Hint: Automatically decomposed array initialization } + replies[7, 0] := 'Why are you interested in whether or not I am*?'; + replies[7, 1] := 'Would you prefer if I were not*?'; + replies[7, 2] := 'Perhaps in your fantasies I am*?'; + { Hint: Automatically decomposed array initialization } + replies[8, 0] := 'How do you know you can''t*?'; + replies[8, 1] := 'Have you tried?'; + replies[8, 2] := 'Perhaps you can now*.'; + { Hint: Automatically decomposed array initialization } + replies[9, 0] := 'Did you come to me because you are*?'; + replies[9, 1] := 'How long have you been*?'; + replies[9, 2] := 'Do you believe it is normal to be*?'; + replies[9, 3] := 'Do you enjoy being*?'; + { Hint: Automatically decomposed array initialization } + replies[10, 0] := 'We were discussing you--not me.'; + replies[10, 1] := 'Oh, I*.'; + replies[10, 2] := 'You''re not really talking about me, are you?'; + { Hint: Automatically decomposed array initialization } + replies[11, 0] := 'What would it mean to you if you got*?'; + replies[11, 1] := 'Why do you want*?'; + replies[11, 2] := 'Suppose you soon got*...'; + replies[11, 3] := 'What if you never got*?'; + replies[11, 4] := 'I sometimes also want*.'; + { Hint: Automatically decomposed array initialization } + replies[12, 0] := 'Why do you ask?'; + replies[12, 1] := 'Does that question interest you?'; + replies[12, 2] := 'What answer would please you the most?'; + replies[12, 3] := 'What do you think?'; + replies[12, 4] := 'Are such questions on your mind often?'; + replies[12, 5] := 'What is it that you really want to know?'; + replies[12, 6] := 'Have you asked anyone else?'; + replies[12, 7] := 'Have you asked such questions before?'; + replies[12, 8] := 'What else comes to mind when you ask that?'; + { Hint: Automatically decomposed array initialization } + replies[13, 0] := 'Names don''t interest me.'; + replies[13, 1] := 'I don''t care about names -- please go on.'; + { Hint: Automatically decomposed array initialization } + replies[14, 0] := 'Is that the real reason?'; + replies[14, 1] := 'Don''t any other reasons come to mind?'; + replies[14, 2] := 'Does that reason explain anything else?'; + replies[14, 3] := 'What other reasons might there be?'; + { Hint: Automatically decomposed array initialization } + replies[15, 0] := 'Please don''t apologize!'; + replies[15, 1] := 'Apologies are not necessary.'; + replies[15, 2] := 'What feelings do you have when you apologize?'; + replies[15, 3] := 'Don''t be so defensive!'; + { Hint: Automatically decomposed array initialization } + replies[16, 0] := 'What does that dream suggest to you?'; + replies[16, 1] := 'Do you dream often?'; + replies[16, 2] := 'What persons appear in your dreams?'; + replies[16, 3] := 'Are you disturbed by your dreams?'; + { Hint: Automatically decomposed array initialization } + replies[17, 0] := 'How do you do ...please state your problem.'; + { Hint: Automatically decomposed array initialization } + replies[18, 0] := 'You don''t seem quite certain.'; + replies[18, 1] := 'Why the uncertain tone?'; + replies[18, 2] := 'Can''t you be more positive?'; + replies[18, 3] := 'You aren''t sure?'; + replies[18, 4] := 'Don''t you know?'; + { Hint: Automatically decomposed array initialization } + replies[19, 0] := 'Are you saying no just to be negative?'; + replies[19, 1] := 'You are being a bit negative.'; + replies[19, 2] := 'Why not?'; + replies[19, 3] := 'Are you sure?'; + replies[19, 4] := 'Why no?'; + { Hint: Automatically decomposed array initialization } + replies[20, 0] := 'Why are you concerned about my*?'; + replies[20, 1] := 'What about your own*?'; + { Hint: Automatically decomposed array initialization } + replies[21, 0] := 'Can you think of a specific example?'; + replies[21, 1] := 'When?'; + replies[21, 2] := 'What are you thinking of?'; + replies[21, 3] := 'Really, always?'; + { Hint: Automatically decomposed array initialization } + replies[22, 0] := 'Do you really think so?'; + replies[22, 1] := 'But you are not sure you*?'; + replies[22, 2] := 'Do you doubt you*?'; + { Hint: Automatically decomposed array initialization } + replies[23, 0] := 'In what way?'; + replies[23, 1] := 'What resemblance do you see?'; + replies[23, 2] := 'What does the similarity suggest to you?'; + replies[23, 3] := 'What other connections do you see?'; + replies[23, 4] := 'Could there really be some connection?'; + replies[23, 5] := 'How?'; + replies[23, 6] := 'You seem quite positive.'; + { Hint: Automatically decomposed array initialization } + replies[24, 0] := 'Are you sure?'; + replies[24, 1] := 'I see.'; + replies[24, 2] := 'I understand.'; + { Hint: Automatically decomposed array initialization } + replies[25, 0] := 'Why do you bring up the topic of friends?'; + replies[25, 1] := 'Do your friends worry you?'; + replies[25, 2] := 'Do your friends pick on you?'; + replies[25, 3] := 'Are you sure you have any friends?'; + replies[25, 4] := 'Do you impose on your friends?'; + replies[25, 5] := 'Perhaps your love for friends worries you.'; + { Hint: Automatically decomposed array initialization } + replies[26, 0] := 'Do computers worry you?'; + replies[26, 1] := 'Are you talking about me in particular?'; + replies[26, 2] := 'Are you frightened by machines?'; + replies[26, 3] := 'Why do you mention computers?'; + replies[26, 4] := 'What do you think machines have to do with your problem?'; + replies[26, 5] := 'Don''t you think computers can help people?'; + replies[26, 6] := 'What is it about machines that worries you?'; + { Hint: Automatically decomposed array initialization } + replies[27, 0] := 'Do you sometimes feel uneasy without a smartphone?'; + replies[27, 1] := 'Have you had these phantasies before?'; + replies[27, 2] := 'Does the world seem more real for you via apps?'; + { Hint: Automatically decomposed array initialization } + replies[28, 0] := 'Tell me more about your family.'; + replies[28, 1] := 'Who else in your family*?'; + replies[28, 2] := 'What does family relations mean for you?'; + replies[28, 3] := 'Come on, How old are you?'; + setupReplies := replies; + +end; + +begin + { Title information } + writeln('************* ELIZA **************'); + writeln('* Original design by J. Weizenbaum'); + writeln('**********************************'); + writeln('* Adapted for Basic on IBM PC by'); + writeln('* - Patricia Danielson'); + writeln('* - Paul Hashfield'); + writeln('**********************************'); + writeln('* Adapted for Structorizer by'); + writeln('* - Kay Gürtzig / FH Erfurt 2016'); + writeln('* Version: 2.3 (2019-11-28)'); + writeln('* (Requires at least Structorizer 3.30-03 to run)'); + writeln('**********************************'); + { Stores the last five inputs of the user in a ring buffer, } + { the second component is the rolling (over-)write index. } + { Hint: Automatically decomposed array initialization } + history.histArray[0] := ''; + history.histArray[1] := ''; + history.histArray[2] := ''; + history.histArray[3] := ''; + history.histArray[4] := ''; + history.histIndex := 0; + replies := setupReplies(); + reflexions := setupReflexions(); + byePhrases := setupGoodByePhrases(); + keyMap := setupKeywords(); + offsets[length(keyMap)-1] := 0; + isGone := false; + { Starter } + writeln('Hi! I\''m your new therapist. My name is Eliza. What\''s your problem?'); + repeat + readln(userInput); + { Converts the input to lowercase, cuts out interpunctation } + { and pads the string } + userInput := normalizeInput(userInput); + isGone := checkGoodBye(userInput, byePhrases); + if (not isGone) then + begin + reply := 'Please don\''t repeat yourself!'; + isRepeated := checkRepetition(history, userInput); + if (not isRepeated) then + begin + findInfo := findKeyword(keyMap, userInput); + keyIndex := findInfo[0]; + if (keyIndex < 0) then + begin + { Should never happen... } + keyIndex := length(keyMap)-1; + end; + entry := keyMap[keyIndex]; + { Variable part of the reply } + varPart := ''; + if (length(entry.keyword) > 0) then + begin + varPart := conjugateStrings(userInput, entry.keyword, findInfo[1], reflexions); + end; + replyRing := replies[entry.index]; + reply := replyRing[offsets[keyIndex]]; + offsets[keyIndex] := (offsets[keyIndex] + 1) mod length(replyRing); + posAster := pos('*', reply); + if (posAster > 0) then + begin + if (varPart = ' ') then + begin + reply := 'You will have to elaborate more for me to help you.'; + end + else + begin + delete(reply, posAster, 1); + insert(varPart, reply, posAster); + end; + end; + reply := adjustSpelling(reply); + end; + writeln(reply); + end; + until (isGone); +end. diff --git a/samples/export/Pascal/SORTING_TEST_MAIN.pas b/samples/export/Pascal/SORTING_TEST_MAIN.pas index c4ec33b8..bfcfbe0a 100644 --- a/samples/export/Pascal/SORTING_TEST_MAIN.pas +++ b/samples/export/Pascal/SORTING_TEST_MAIN.pas @@ -2,7 +2,7 @@ { to allow performance comparison via execution counting ("Collect Runtime Data" should } { sensibly be switched on). } { Requested input data are: Number of elements (size) and filing mode. } -{ Generated by Structorizer 3.30-02 } +{ Generated by Structorizer 3.30-03 } { } { Copyright (C) 2019-10-02 Kay Gürtzig } { License: GPLv3-link } @@ -13,17 +13,16 @@ program SORTING_TEST_MAIN; var - values3: ???; { FIXME! } - values2: ???; { FIXME! } - values1: ???; { FIXME! } + values3: array of ???; { FIXME! } + values2: array of ???; { FIXME! } + values1: array of Longint; show: ???; { FIXME! } - ok3: ???; { FIXME! } - ok2: ???; { FIXME! } - ok1: ???; { FIXME! } + ok3: Boolean; + ok2: Boolean; + ok1: Boolean; modus: ???; { FIXME! } i: Longint; elementCount: ???; { FIXME! } - [i]: ???; { FIXME! } { Implements the well-known BubbleSort algorithm. } @@ -292,7 +291,7 @@ function heapSort(values: {type?}): Integer; end; end; end; - { Kopiere das Array für exakte Vergleichbarkeit } + { Copy the array for exact comparability } for i := 0 to elementCount-1 do begin values2[i] := values1[i]; diff --git a/samples/export/Pascal/TextDemo.pas b/samples/export/Pascal/TextDemo.pas new file mode 100644 index 00000000..185f3edc --- /dev/null +++ b/samples/export/Pascal/TextDemo.pas @@ -0,0 +1,1336 @@ +{ Demo program for routine drawText() } +{ Asks the user to enter a text, a wanted text height and colour, } +{ and then draws this string onto the turtle screen. Places every } +{ entered text to a new line. } +{ Generated by Structorizer 3.30-03 } +{ } +{ Copyright (C) 2019-10-10 Kay Gürtzig } +{ License: GPLv3-link } +{ GNU General Public License (V 3) } +{ https://www.gnu.org/licenses/gpl.html } +{ http://www.gnu.de/documents/gpl.de.html } +{ } +program TextDemo; + +var + y: Longint; + { Make sure the content is interpreted as string } + text: ???; { FIXME! } + height: ???; { FIXME! } + colour: ???; { FIXME! } + + +{ Draws a blank for font height h, ignoring the colorNo } +procedure blank(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + +begin + width := h/2.0; + penUp(); + right(90); + forward(width); { color = ffffff } + left(90); + +end; + +procedure forward(len: {type?}; color: {type?}); + + +begin + case (color) of + 1: + begin + forward(len); { color = ffffff } + end; + 2: + begin + forward(len); { color = ff8080 } + end; + 3: + begin + forward(len); { color = ffff80 } + end; + 4: + begin + forward(len); { color = 80ff80 } + end; + 5: + begin + forward(len); { color = 80ffff } + end; + 6: + begin + forward(len); { color = 0080ff } + end; + 7: + begin + forward(len); { color = ff80c0 } + end; + 8: + begin + forward(len); { color = c0c0c0 } + end; + 9: + begin + forward(len); { color = ff8000 } + end; + 10: + begin + forward(len); { color = 8080ff } + end; + end; + +end; + +{ Draws letter A in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterA(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle: Double; + hypo: Double; + +begin + width := h/2.0; + hypo := sqrt(h*h + width*width/4.0); + rotAngle := toDegrees(atan(width/2.0/h)); + right(rotAngle); + forward(hypo/2.0, colorNo); + right(90 - rotAngle); + forward(width/2.0, colorNo); + penUp(); + backward(width/2.0); { color = ffffff } + penDown(); + left(90 - rotAngle); + forward(hypo/2.0, colorNo); + left(2*rotAngle); + forward(-hypo, colorNo); + right(rotAngle); + +end; + +{ Draws letter E in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterE(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + +begin + width := h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); { color = ffffff } + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); { color = ffffff } + left(90); + penDown(); + forward(width, colorNo); + left(90); + +end; + +{ Draws letter F in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterF(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + +begin + width := h/2.0; + forward(h, colorNo); + right(90); + forward(width, colorNo); + right(90); + penUp(); + forward(h/2.0); { color = ffffff } + right(90); + penDown(); + forward(width, colorNo); + left(90); + penUp(); + forward(h/2.0); { color = ffffff } + left(90); + forward(width); { color = ffffff } + penDown(); + left(90); + +end; + +{ Draws letter H in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterH(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + +begin + width := h/2.0; + forward(h, colorNo); + penUp(); + right(90); + forward(width); { color = ffffff } + right(90); + penDown(); + forward(h/2.0, colorNo); + right(90); + forward(width, colorNo); + penUp(); + backward(width); { color = ffffff } + left(90); + penDown(); + forward(h/2.0, colorNo); + left(180); + +end; + +{ Draws letter I in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterI(h: {type?}; colorNo: {type?}); + +var + { Cathetus of the corner triangle outside the octagon } + c: ???; { FIXME! } + { Octagon edge length } + b: ???; { FIXME! } + +begin + { Octagon edge length } + b := h * 0.5 / (sqrt(2.0) + 1); + { Cathetus of the corner triangle outside the octagon } + c := b / sqrt(2.0); + penUp(); + right(90); + forward(c); { color = ffffff } + penDown(); + forward(b, colorNo); + penUp(); + backward(b/2.0); { color = ffffff } + left(90); + penDown(); + forward(h, colorNo); + penUp(); + right(90); + backward(b/2.0); { color = ffffff } + penDown(); + forward(b, colorNo); + penUp(); + forward(b/2 + c); { color = ffffff } + left(90); + backward(h); { color = ffffff } + penDown(); + +end; + +{ Draws letter K in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterK(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + diag: ???; { FIXME! } + +begin + width := h/2.0; + diag := h/sqrt(2.0); + forward(h, colorNo); + penUp(); + right(90); + forward(width); { color = ffffff } + right(135); + penDown(); + forward(diag, colorNo); + left(90); + forward(diag, colorNo); + left(135); + +end; + +{ Draws letter L in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterL(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + +begin + width := h/2.0; + forward(h, colorNo); + penUp(); + backward(h); { color = ffffff } + right(90); + penDown(); + forward(width, colorNo); + left(90); + +end; + +{ Draws letter M in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterM(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle: Double; + hypo: ???; { FIXME! } + +begin + width := h/2.0; + hypo := sqrt(width*width + h*h)/2.0; + rotAngle := toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + left(rotAngle); + forward(-h, colorNo); + +end; + +{ Draws letter N in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterN(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle: Double; + hypo: Double; + +begin + width := h/2.0; + hypo := sqrt(width*width + h*h); + rotAngle := toDegrees(atan(width/h)); + forward(h, colorNo); + left(rotAngle); + forward(-hypo, colorNo); + right(rotAngle); + forward(h, colorNo); + penUp(); + backward(h); { color = ffffff } + penDown(); + +end; + +{ Draws letter T in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterT(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + +begin + width := h/2.0; + penUp(); + forward(h); { color = ffffff } + penDown(); + right(90); + forward(width, colorNo); + penUp(); + backward(width/2.0); { color = ffffff } + penDown(); + right(90); + forward(h, colorNo); + left(90); + penUp(); + forward(width/2.0); { color = ffffff } + penDown(); + left(90); + +end; + +{ Draws letter V in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterV(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle: Double; + hypo: Double; + +begin + width := h/2.0; + hypo := sqrt(h*h + width*width/4.0); + rotAngle := toDegrees(atan(width/2.0/h)); + penUp(); + forward(h); { color = ffffff } + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); { color = ffffff } + penDown(); + +end; + +{ Draws letter W in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterW(h: {type?}; colorNo: {type?}); + +var + width_3: ???; { FIXME! } + width: ???; { FIXME! } + rotAngle: Double; + hypo: Double; + +begin + width := h/2.0; + width_3 := width/3.0; + hypo := sqrt(width_3*width_3 + h*h); + rotAngle := toDegrees(atan(width_3/h)); + penUp(); + forward(h); { color = ffffff } + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width_3); { color = ffffff } + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(2*rotAngle); + forward(hypo, colorNo); + penUp(); + left(rotAngle); + backward(h); { color = ffffff } + penDown(); + +end; + +{ Draws letter X in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterX(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle: Double; + hypo: Double; + +begin + width := h/2.0; + hypo := sqrt(width*width + h*h); + rotAngle := toDegrees(atan(width/h)); + right(rotAngle); + forward(hypo, colorNo); + penUp(); + left(90+rotAngle); + forward(width); { color = ffffff } + right(90-rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); + +end; + +{ Draws letter Y in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterY(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle: Double; + hypo: ???; { FIXME! } + +begin + width := h/2.0; + hypo := sqrt(width*width + h*h)/2.0; + rotAngle := toDegrees(atan(width/h)); + penUp(); + forward(h); { color = ffffff } + left(rotAngle); + penDown(); + forward(-hypo, colorNo); + right(rotAngle); + penUp(); + backward(h/2.0); { color = ffffff } + penDown(); + forward(h/2.0, colorNo); + right(rotAngle); + forward(hypo, colorNo); + left(rotAngle); + penUp(); + backward(h); { color = ffffff } + penDown(); + +end; + +{ Draws letter Z in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterZ(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle: Double; + hypo: Double; + +begin + width := h/2.0; + hypo := sqrt(width*width + h*h); + rotAngle := toDegrees(atan(width/h)); + penUp(); + forward(h); { color = ffffff } + right(90); + penDown(); + forward(width, colorNo); + left(90-rotAngle); + forward(-hypo, colorNo); + right(90-rotAngle); + forward(width, colorNo); + left(90); + +end; + +{ Draws nEdges edges of a regular n-polygon with edge length a } +{ counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. } +procedure polygonPart(a: Double; n: Longint; ctrclkws: boolean; nEdges: Longint; color: Longint); + +var + rotAngle: ???; { FIXME! } + k: Longint; + +begin + rotAngle := 360.0/n; + if (ctrclkws) then + begin + rotAngle := -rotAngle; + end; + for k := 1 to nEdges do + begin + right(rotAngle); + forward(a, color); + end; + +end; + +{ Draws a dummy character (small centered square) with font height h and } +{ the colour encoded by colorNo } +procedure charDummy(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + d: ???; { FIXME! } + { Cathetus of the corner triangle outside the octagon } + c: ???; { FIXME! } + { Octagon edge length (here: edge lengzh of the square) } + b: ???; { FIXME! } + +begin + width := h / 2.0; + { Octagon edge length (here: edge lengzh of the square) } + b := width / (sqrt(2.0) + 1); + { Cathetus of the corner triangle outside the octagon } + c := (width - b) / 2.0; + d := b / sqrt(2.0); + penUp(); + forward(h/2.0-b/2.0); { color = ffffff } + right(90); + forward(c); { color = ffffff } + right(90); + penDown(); + { Draws the square with edge length b } + polygonPart(b, 4, true, 4, colorNo); + penUp(); + left(90); + forward(b + c); { color = ffffff } + left(90); + backward(h/2.0-b/2.0); { color = ffffff } + penDown(); + +end; + +{ Draws a comma in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure comma(h: {type?}; colorNo: {type?}); + +var + rotAngle: Double; + hypo: ???; { FIXME! } + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + rotAngle := toDegrees(atan(0.5)); + hypo := c * sqrt(1.25); + penUp(); + right(90); + forward((c+b)/2.0 + c); { color = ffffff } + penDown(); + { Counterclockwise draw 3 edges of a square with edge length c } + { in the colour endcoded by colorNo } + polygonPart(c, 4, true, 3, colorNo); + left(90); + forward(c/2.0, colorNo); + right(90); + forward(c, colorNo); + left(180 - rotAngle); + forward(hypo, colorNo); + penUp(); + right(90 - rotAngle); + forward((c + b)/2.0); { color = ffffff } + left(90); + penDown(); + +end; + +{ Draws an exclamation mark in the colour encoded by colorNo with font height h } +{ from the current turtle position. } +procedure exclMk(h: {type?}; colorNo: {type?}); + +var + width: ???; { FIXME! } + rotAngle2: Double; + { 360°/8 } + rotAngle: Longint; + length2: ???; { FIXME! } + length1: ???; { FIXME! } + hypo: Double; + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + width := h/2.0; + length1 := h - (b+c)/2.0; + length2 := length1 - 2*c; + hypo := sqrt(width*width/16.0 + length2*length2); + { 360°/8 } + rotAngle := 45; + rotAngle2 := toDegrees(atan(width/4.0/length2)); + penUp(); + forward(length1); { color = ffffff } + right(90); + forward(width/2.0); { color = ffffff } + left(90 + rotAngle); + penDown(); + { Clockwise draw 5 edges of an octagon with edge length b/2 } + { in the colour endcoded by colorNo } + polygonPart(b/2.0, 8, false, 5, colorNo); + right(rotAngle2); + forward(hypo, colorNo); + left(2*rotAngle2); + forward(-hypo, colorNo); + penUp(); + forward(hypo); { color = ffffff } + right(rotAngle2); + forward(c); { color = ffffff } + left(90); + forward(c/2.0); { color = ffffff } + penDown(); + { Counterclockwise draw all 4 edges of a squarfe with edge length c } + { in the colour endcoded by colorNo } + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); { color = ffffff } + left(90); + backward(c); { color = ffffff } + penDown(); + +end; + +{ Draws a full stop in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure fullSt(h: {type?}; colorNo: {type?}); + +var + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + penUp(); + right(90); + forward((c+b)/2.0 + c); { color = ffffff } + penDown(); + { Counterclockwise draw all 4 edges of a squarfe with edge length c } + { in the colour endcoded by colorNo } + polygonPart(c, 4, true, 4, colorNo); + penUp(); + forward((c + b)/2.0); { color = ffffff } + left(90); + penDown(); + +end; + +{ Draws letter B in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterB(h: {type?}; colorNo: {type?}); + +var + { Cathetus of the outer corner triangle of the octagon } + c: ???; { FIXME! } + { Octagon edge length } + b: ???; { FIXME! } + +begin + { Octagon edge length } + b := h * 0.5 / (sqrt(2.0) + 1); + { Cathetus of the outer corner triangle of the octagon } + c := b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + { Clockwise draw 4 edges of an octagon with edge length b } + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + c); { color = ffffff } + penDown(); + { Clockwise draw 4 edges of an octagon with edge length b } + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); { color = ffffff } + penDown(); + left(90); + +end; + +{ Draws letter C in the colour encoded by colorNo with font height h } +{ from the current turtle position. } +procedure letterC(h: {type?}; colorNo: {type?}); + +var + { 360°/8 } + rotAngle: Longint; + { Cathetus of the outer trinagle at the octagon corner } + c: ???; { FIXME! } + { Octagon edge length } + b: ???; { FIXME! } + +begin + { Octagon edge length } + b := h * 0.5 / (sqrt(2.0) + 1); + { Cathetus of the outer trinagle at the octagon corner } + c := b / sqrt(2.0); + { 360°/8 } + rotAngle := 45; + penUp(); + forward(c); { color = ffffff } + penDown(); + right(180); + { Clockwise draws 3 edges of an octagon with edge length b in the colour } + { encoded by colorNo } + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + penUp(); + forward(2*b + 2*c); { color = ffffff } + penDown(); + { Counterclockwise draws 4 edges of an octagon with edge length b } + { iin the colour encoded by colorNo } + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); { color = ffffff } + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); + +end; + +{ Draws letter D in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterD(h: {type?}; colorNo: {type?}); + +var + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + { Clockwise draw 2 edges of an octagon with edge length b in the colour } + { encoded by colorNo } + polygonPart(b, 8, false, 2, colorNo); + forward(b + 2*c, colorNo); + { Clockwise draw 2 edges of an octagon with edge length b in the colour } + { encoded by colorNo } + polygonPart(b, 8, false, 2, colorNo); + forward(c, colorNo); + penUp(); + left(180); + forward(b + 2*c); { color = ffffff } + penDown(); + left(90); + +end; + +{ Draws letter G in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterG(h: {type?}; colorNo: {type?}); + +var + { Cathetus of the corner triangle outside the octagon. } + c: ???; { FIXME! } + { Octagon edge length } + b: ???; { FIXME! } + +begin + { Octagon edge length } + b := h * 0.5 / (sqrt(2.0) + 1); + { Cathetus of the corner triangle outside the octagon. } + c := b / sqrt(2.0); + penUp(); + forward(c); { color = ffffff } + penDown(); + right(180); + { Counterclockwise draw 4 edges of an octagon with edge length b in } + { the colour encoded by colorNo } + polygonPart(b, 8, true, 4, colorNo); + forward(c, colorNo); + left(90); + forward(b/2.0 + c, colorNo); + penUp(); + backward(b/2.0 + c); { color = ffffff } + right(90); + forward(b + c); { color = ffffff } + penDown(); + { Counterclockwise draw 4 edges of an octagon with edge length b in } + { the colour encoded by colorNo } + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); { color = ffffff } + left(90); + forward(b + 2*c, colorNo); + penDown(); + left(90); + +end; + +{ Draws letter J in colour encoded by colorNo with font height h } +{ from the current turtle position. } +procedure letterJ(h: {type?}; colorNo: {type?}); + +var + { 360°/8 } + rotAngle: Longint; + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + { 360°/8 } + rotAngle := 45; + penUp(); + forward(c); { color = ffffff } + penDown(); + right(180); + { Counterclockwise draw 3 edges of an octagon with edge length b in } + { the colour encoded by colorNo } + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); { color = ffffff } + penDown(); + +end; + +{ Draws letter O in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterO(h: {type?}; colorNo: {type?}); + +var + { Cathetus of the corner triangle outside the octagon } + c: ???; { FIXME! } + { Octagon edge length } + b: ???; { FIXME! } + +begin + { Octagon edge length } + b := h * 0.5 / (sqrt(2.0) + 1); + { Cathetus of the corner triangle outside the octagon } + c := b / sqrt(2.0); + penUp(); + forward(c); { color = ffffff } + penDown(); + right(180); + { Counterclockwise draw 4 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + { Counterclockwise draw 4 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); { color = ffffff } + left(90); + forward(b + 2*c); { color = ffffff } + penDown(); + left(90); + +end; + +{ Draws letter P in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterP(h: {type?}; colorNo: {type?}); + +var + { Cathetus of the corner triangle outside the octagon } + c: ???; { FIXME! } + { Octagon edge length } + b: ???; { FIXME! } + +begin + { Octagon edge length } + b := h * 0.5 / (sqrt(2.0) + 1); + { Cathetus of the corner triangle outside the octagon } + c := b / sqrt(2.0); + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + { Clockwise draw 4 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + penUp(); + backward(b + 2*c); { color = ffffff } + left(90); + forward(b + 2*c); { color = ffffff } + penDown(); + left(180); + +end; + +{ Draws letter Q in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterQ(h: {type?}; colorNo: {type?}); + +var + { 360°/8 } + rotAngle: Longint; + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + { 360°/8 } + rotAngle := 45; + penUp(); + forward(c); { color = ffffff } + penDown(); + right(180); + { Counterclockwise draw 4 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + { Counterclockwise draw 4 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, true, 4, colorNo); + forward(b + 2*c, colorNo); + penUp(); + forward(c); { color = ffffff } + left(90); + forward(b + 2*c); { color = ffffff } + right(rotAngle); + backward(b); { color = ffffff } + penDown(); + forward(b, colorNo); + left(90 + rotAngle); + +end; + +{ Zeichnet den Buchstaben R von der Turtleposition aus } +{ mit Zeilenhöhe h } +procedure letterR(h: {type?}; colorNo: {type?}); + +var + { 360°/8 } + rotAngle: Longint; + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + { 360°/8 } + rotAngle := 45; + forward(h, colorNo); + right(90); + forward(c+b, colorNo); + { Clockwise draw 4 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, false, 4, colorNo); + forward(c, colorNo); + left(90 + rotAngle); + forward(sqrt(2.0)*(b + 2*c), colorNo); + left(90 + rotAngle); + +end; + +{ Draws letter S in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterS(h: {type?}; colorNo: {type?}); + +var + { 360°/8 } + rotAngle: Longint; + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + { 360°/8 } + rotAngle := 45; + penUp(); + forward(c); { color = ffffff } + penDown(); + right(180); + { Counterclockwise draw 6 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, true, 6, colorNo); + { Clockwise draw 5 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, false, 5, colorNo); + right(rotAngle); + penUp(); + forward(2*b + 3*c); { color = ffffff } + penDown(); + left(180); + +end; + +{ Draws letter U in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure letterU(h: {type?}; colorNo: {type?}); + +var + { 360°/8 } + rotAngle: Longint; + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { edge length of a regular octagon } + b: ???; { FIXME! } + +begin + { edge length of a regular octagon } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + { 360°/8 } + rotAngle := 45; + penUp(); + forward(c); { color = ffffff } + penDown(); + forward(h - c, colorNo); + penUp(); + backward(h-c); { color = ffffff } + penDown(); + right(180); + { Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo } + polygonPart(b, 8, true, 3, colorNo); + left(rotAngle); + forward(h - c, colorNo); + penUp(); + backward(h); { color = ffffff } + penDown(); + +end; + +{ Draws a question mark in colour specified by colorNo with font height h } +{ from the current turtle position. } +procedure qstnMk(h: {type?}; colorNo: {type?}); + +var + { 360°/8 } + rotAngle: Longint; + { Eckenlänge außen am Achteck } + c: ???; { FIXME! } + { Achteck-Kantenlänge } + b: ???; { FIXME! } + +begin + { Achteck-Kantenlänge } + b := h * 0.5 / (sqrt(2.0) + 1); + { Eckenlänge außen am Achteck } + c := b / sqrt(2.0); + { 360°/8 } + rotAngle := 45; + penUp(); + forward(h-c); { color = ffffff } + penDown(); + { Counterclockwise draw 5 edges of an octagon with edge length b } + { in the colour endcoded by colorNo } + polygonPart(b, 8, false, 5, colorNo); + forward(c, colorNo); + left(rotAngle); + forward(b/2.0, colorNo); + penUp(); + forward(c); { color = ffffff } + left(90); + forward(c/2.0); { color = ffffff } + penDown(); + { Counterclockwise draw all 4 edges of a squarfe with edge length c } + { in the colour endcoded by colorNo } + polygonPart(c, 4, false, 4, colorNo); + penUp(); + forward((c + b)/2.0); { color = ffffff } + left(90); + backward(c); { color = ffffff } + penDown(); + +end; + +{ Has the turtle draw the given string 'text´ with font height 'h´ (in } +{ pixels) and the colour coded by integer 'c´ from the current Turtle } +{ position to the Turtle canvas. If the turtle looks North then } +{ the text will be written rightwards. In the event, the turtle will be } +{ placed behind the text in original orientation (such that the next text } +{ would be written like a continuation. Colour codes: } +{ 1 = black } +{ 2 = red } +{ 3 = yellow } +{ 4 = green } +{ 5 = cyan } +{ 6 = blue } +{ 7 = pink } +{ 8 = grey } +{ 9 = orange } +{ 10 = violet } +{ All letters (ASCII) will be converted to uppercase, digits cannot } +{ be represented, the set of representable special characters is: } +{ '.', ',', '!', '?'. Other characters will be shown as a small } +{ centred square (dummy character). } +procedure drawText(text: string; h: Longint; c: Longint); + +var + letter: String; + k: Longint; + gap: ???; { FIXME! } + +begin + gap := h/10.0; + for k := 1 to length(text) do + begin + letter := uppercase(copy(text, k, 1)); + if (letter = ',') then + begin + comma(h,c); + end + else + begin + { "," cannot be chacked against because the comma is misinterpreted } + { as selector list separator. } + case (letter) of + "A": + begin + letterA(h,c); + end; + "B": + begin + letterB(h,c); + end; + "C": + begin + letterC(h,c); + end; + "D": + begin + letterD(h,c); + end; + "E": + begin + letterE(h,c); + end; + "F": + begin + letterF(h,c); + end; + "G": + begin + letterG(h,c); + end; + "H": + begin + letterH(h,c); + end; + "I": + begin + letterI(h,c); + end; + "J": + begin + letterJ(h,c); + end; + "K": + begin + letterK(h,c); + end; + "L": + begin + letterL(h,c); + end; + "M": + begin + letterM(h,c); + end; + "N": + begin + letterN(h,c); + end; + "O": + begin + letterO(h,c); + end; + "P": + begin + letterP(h,c); + end; + "Q": + begin + letterQ(h,c); + end; + "R": + begin + letterR(h,c); + end; + "S": + begin + letterS(h,c); + end; + "T": + begin + letterT(h,c); + end; + "U": + begin + letterU(h,c); + end; + "V": + begin + letterV(h,c); + end; + "W": + begin + letterW(h,c); + end; + "X": + begin + letterX(h,c); + end; + "Y": + begin + letterY(h,c); + end; + "Z": + begin + letterZ(h,c); + end; + " ": + begin + blank(h,c); + end; + "!": + begin + exclMk(h,c); + end; + "?": + begin + qstnMk(h,c); + end; + ".": + begin + fullSt(h,c); + end; + else + charDummy(h,c); + end; + end; + right(90); + penUp(); + forward(gap); { color = ffffff } + penDown(); + left(90); + end; + +end; + +begin + writeln('This is a demo program for text writing with Turleizer.'); + showTurtle(); + penDown(); + y := 0; + repeat + write('Enter some text (empty string to exit)'); readln(text); + { Make sure the content is interpreted as string } + text := '' + text; + if (text <> '') then + begin + repeat + write('Height of the text (pixels)'); readln(height); + until (height >= 5); + repeat + write('Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)'); readln(colour); + until (colour >= 1 and colour <= 10); + y := y + height + 2; + gotoXY(0, y - 2); + drawText(text, height, colour); + end; + until (text = ''); + gotoXY(0, y + 15); + drawText('Thank you, bye.', 10, 4); + hideTurtle(); +end. diff --git a/samples/export/Perl/ELIZA_2.3.pl b/samples/export/Perl/ELIZA_2.3.pl new file mode 100644 index 00000000..ce381385 --- /dev/null +++ b/samples/export/Perl/ELIZA_2.3.pl @@ -0,0 +1,441 @@ +#!/usr/bin/perl +# Generated by Structorizer 3.30-03 +# +# Copyright (C) 2018-05-14 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# + +use strict; +use warnings; +use Class::Struct; + +# Cares for correct letter case among others +sub adjustSpelling { + my $sentence = $_[0]; + + my $word; + my $start; + my $result; + my $position; + + $result = $sentence; + $position = 1; + + while ( ($position <= length($sentence)) && (copy($sentence, $position, 1) == " ") ) { + $position = $position + 1; + } + + + if ( $position <= length($sentence) ) { + $start = copy($sentence, 1, $position); + delete($result, 1, $position); + insert(uppercase($start), $result, 1); + } + + + my @array324bf690 = (" i ", " i\'") + foreach $word (@array324bf690) { + $position = pos($word, $result); + + while ( $position > 0 ) { + delete($result, $position+1, 1); + insert("I", $result, $position+1); + $position = pos($word, $result); + } + + } + + + return $result; +} + +# Checks whether the given text contains some kind of +# good-bye phrase inducing the end of the conversation +# and if so writes a correspding good-bye message and +# returns true, otherwise false +sub checkGoodBye { + my $text = $_[0]; + my $phrases = $_[1]; + + my $saidBye; + my $pair; + + + foreach $pair (@$phrases) { + + if ( pos($pair[0], $text) > 0 ) { + $saidBye = true; + print $pair[1], "\n"; + return true; + } + + } + + return false; +} + +# Checks whether newInput has occurred among the recently cached +# input strings in the histArray component of history and updates the history. +sub checkRepetition { + my $history = $_[0]; + my $newInput = $_[1]; + + my $i; + my $histDepth; + my $hasOccurred; + + $hasOccurred = false; + + if ( length($newInput) > 4 ) { + $histDepth = length($$history->histArray); + + for ($i = 0; $i <= $histDepth-1; $i += (1)) { + + if ( $newInput == $$history->histArray[$i] ) { + $hasOccurred = true; + } + + } + + $$history->histArray[$$history->histIndex] = $newInput; + $$history->histIndex = ($$history->histIndex + 1) % ($histDepth); + } + + return $hasOccurred; +} + +sub conjugateStrings { + my $sentence = $_[0]; + my $key = $_[1]; + my $keyPos = $_[2]; + my $flexions = $_[3]; + + my $right; + my $result; + my $position; + my $pair; + my $left; + + $result = " " + copy($sentence, $keyPos + length($key), length($sentence)) + " "; + + foreach $pair (@$flexions) { + $left = ""; + $right = $result; + $position = pos($pair[0], $right); + + while ( $position > 0 ) { + $left = $left + copy($right, 1, $position-1) + $pair[1]; + $right = copy($right, $position + length($pair[0]), length($right)); + $position = pos($pair[0], $right); + } + + $result = $left + $right; + } + + # Eliminate multiple spaces + $position = pos(" ", $result); + + while ( $position > 0 ) { + $result = copy($result, 1, $position-1) + copy($result, $position+1, length($result)); + $position = pos(" ", $result); + } + + + return $result; +} + +# Looks for the occurrence of the first of the strings +# contained in keywords within the given sentence (in +# array order). +# Returns an array of +# 0: the index of the first identified keyword (if any, otherwise -1), +# 1: the position inside sentence (0 if not found) +sub findKeyword { + my $keyMap = $_[0]; + my $sentence = $_[1]; + + my @result; + my $position; + my $i; + my $entry; + + # Contains the index of the keyword and its position in sentence + @result = (-1,0); + $i = 0; + + while ( ($result[0] < 0) && ($i < length($keyMap)) ) { + var $entry: KeyMapEntry = $keyMap[$i]; + $position = pos($entry->keyword, $sentence); + + if ( $position > 0 ) { + $result[0] = $i; + $result[1] = $position; + } + + $i = $i+1; + } + + + return $result; +} + +# Converts the sentence to lowercase, eliminates all +# interpunction (i.e. ',', '.', ';'), and pads the +# sentence among blanks +sub normalizeInput { + my $sentence = $_[0]; + + my $symbol; + my $result; + my $position; + + $sentence = lowercase($sentence); + + my @arrayb4f79f = ('.', ',', ';', '!', '?') + foreach $symbol (@arrayb4f79f) { + $position = pos($symbol, $sentence); + + while ( $position > 0 ) { + $sentence = copy($sentence, 1, $position-1) + copy($sentence, $position+1, length($sentence)); + $position = pos($symbol, $sentence); + } + + } + + $result = " " + $sentence + " "; + + return $result; +} + +sub setupGoodByePhrases { + + my @phrases; + + $phrases[0] = (" shut", "Okay. If you feel that way I\'ll shut up. ... Your choice."); + $phrases[1] = ("bye", "Well, let\'s end our talk for now. See you later. Bye."); + return @phrases; +} + +# The lower the index the higher the rank of the keyword (search is sequential). +# The index of the first keyword found in a user sentence maps to a respective +# reply ring as defined in `setupReplies()´. +sub setupKeywords { + + my @keywords; + + # The empty key string (last entry) is the default clause - will always be found + $keywords[39] = KeyMapEntry("", 29); + $keywords[0] = KeyMapEntry("can you ", 0); + $keywords[1] = KeyMapEntry("can i ", 1); + $keywords[2] = KeyMapEntry("you are ", 2); + $keywords[3] = KeyMapEntry("you\'re ", 2); + $keywords[4] = KeyMapEntry("i don't ", 3); + $keywords[5] = KeyMapEntry("i feel ", 4); + $keywords[6] = KeyMapEntry("why don\'t you ", 5); + $keywords[7] = KeyMapEntry("why can\'t i ", 6); + $keywords[8] = KeyMapEntry("are you ", 7); + $keywords[9] = KeyMapEntry("i can\'t ", 8); + $keywords[10] = KeyMapEntry("i am ", 9); + $keywords[11] = KeyMapEntry("i\'m ", 9); + $keywords[12] = KeyMapEntry("you ", 10); + $keywords[13] = KeyMapEntry("i want ", 11); + $keywords[14] = KeyMapEntry("what ", 12); + $keywords[15] = KeyMapEntry("how ", 12); + $keywords[16] = KeyMapEntry("who ", 12); + $keywords[17] = KeyMapEntry("where ", 12); + $keywords[18] = KeyMapEntry("when ", 12); + $keywords[19] = KeyMapEntry("why ", 12); + $keywords[20] = KeyMapEntry("name ", 13); + $keywords[21] = KeyMapEntry("cause ", 14); + $keywords[22] = KeyMapEntry("sorry ", 15); + $keywords[23] = KeyMapEntry("dream ", 16); + $keywords[24] = KeyMapEntry("hello ", 17); + $keywords[25] = KeyMapEntry("hi ", 17); + $keywords[26] = KeyMapEntry("maybe ", 18); + $keywords[27] = KeyMapEntry(" no", 19); + $keywords[28] = KeyMapEntry("your ", 20); + $keywords[29] = KeyMapEntry("always ", 21); + $keywords[30] = KeyMapEntry("think ", 22); + $keywords[31] = KeyMapEntry("alike ", 23); + $keywords[32] = KeyMapEntry("yes ", 24); + $keywords[33] = KeyMapEntry("friend ", 25); + $keywords[34] = KeyMapEntry("computer", 26); + $keywords[35] = KeyMapEntry("bot ", 26); + $keywords[36] = KeyMapEntry("smartphone", 27); + $keywords[37] = KeyMapEntry("father ", 28); + $keywords[38] = KeyMapEntry("mother ", 28); + return @keywords; +} + +# Returns an array of pairs of mutualy substitutable +sub setupReflexions { + + my @reflexions; + + $reflexions[0] = (" are ", " am "); + $reflexions[1] = (" were ", " was "); + $reflexions[2] = (" you ", " I "); + $reflexions[3] = (" your", " my"); + $reflexions[4] = (" i\'ve ", " you\'ve "); + $reflexions[5] = (" i\'m ", " you\'re "); + $reflexions[6] = (" me ", " you "); + $reflexions[7] = (" my ", " your "); + $reflexions[8] = (" i ", " you "); + $reflexions[9] = (" am ", " are "); + return @reflexions; +} + +# This routine sets up the reply rings addressed by the key words defined in +# routine `setupKeywords()´ and mapped hitherto by the cross table defined +# in `setupMapping()´ +sub setupReplies { + + my @setupReplies; + my @replies; + + # We start with the highest index for performance reasons + # (is to avoid frequent array resizing) + $replies[29] = ( "Say, do you have any psychological problems?", "What does that suggest to you?", "I see.", "I'm not sure I understand you fully.", "Come come elucidate your thoughts.", "Can you elaborate on that?", "That is quite interesting."); + $replies[0] = ( "Don't you believe that I can*?", "Perhaps you would like to be like me?", "You want me to be able to*?"); + $replies[1] = ( "Perhaps you don't want to*?", "Do you want to be able to*?"); + $replies[2] = ( "What makes you think I am*?", "Does it please you to believe I am*?", "Perhaps you would like to be*?", "Do you sometimes wish you were*?"); + $replies[3] = ( "Don't you really*?", "Why don't you*?", "Do you wish to be able to*?", "Does that trouble you*?"); + $replies[4] = ( "Do you often feel*?", "Are you afraid of feeling*?", "Do you enjoy feeling*?"); + $replies[5] = ( "Do you really believe I don't*?", "Perhaps in good time I will*.", "Do you want me to*?"); + $replies[6] = ( "Do you think you should be able to*?", "Why can't you*?"); + $replies[7] = ( "Why are you interested in whether or not I am*?", "Would you prefer if I were not*?", "Perhaps in your fantasies I am*?"); + $replies[8] = ( "How do you know you can't*?", "Have you tried?","Perhaps you can now*."); + $replies[9] = ( "Did you come to me because you are*?", "How long have you been*?", "Do you believe it is normal to be*?", "Do you enjoy being*?"); + $replies[10] = ( "We were discussing you--not me.", "Oh, I*.", "You're not really talking about me, are you?"); + $replies[11] = ( "What would it mean to you if you got*?", "Why do you want*?", "Suppose you soon got*...", "What if you never got*?", "I sometimes also want*."); + $replies[12] = ( "Why do you ask?", "Does that question interest you?", "What answer would please you the most?", "What do you think?", "Are such questions on your mind often?", "What is it that you really want to know?", "Have you asked anyone else?", "Have you asked such questions before?", "What else comes to mind when you ask that?"); + $replies[13] = ( "Names don't interest me.", "I don't care about names -- please go on."); + $replies[14] = ( "Is that the real reason?", "Don't any other reasons come to mind?", "Does that reason explain anything else?", "What other reasons might there be?"); + $replies[15] = ( "Please don't apologize!", "Apologies are not necessary.", "What feelings do you have when you apologize?", "Don't be so defensive!"); + $replies[16] = ( "What does that dream suggest to you?", "Do you dream often?", "What persons appear in your dreams?", "Are you disturbed by your dreams?"); + $replies[17] = ( "How do you do ...please state your problem."); + $replies[18] = ( "You don't seem quite certain.", "Why the uncertain tone?", "Can't you be more positive?", "You aren't sure?", "Don't you know?"); + $replies[19] = ( "Are you saying no just to be negative?", "You are being a bit negative.", "Why not?", "Are you sure?", "Why no?"); + $replies[20] = ( "Why are you concerned about my*?", "What about your own*?"); + $replies[21] = ( "Can you think of a specific example?", "When?", "What are you thinking of?", "Really, always?"); + $replies[22] = ( "Do you really think so?", "But you are not sure you*?", "Do you doubt you*?"); + $replies[23] = ( "In what way?", "What resemblance do you see?", "What does the similarity suggest to you?", "What other connections do you see?", "Could there really be some connection?", "How?", "You seem quite positive."); + $replies[24] = ( "Are you sure?", "I see.", "I understand."); + $replies[25] = ( "Why do you bring up the topic of friends?", "Do your friends worry you?", "Do your friends pick on you?", "Are you sure you have any friends?", "Do you impose on your friends?", "Perhaps your love for friends worries you."); + $replies[26] = ( "Do computers worry you?", "Are you talking about me in particular?", "Are you frightened by machines?", "Why do you mention computers?", "What do you think machines have to do with your problem?", "Don't you think computers can help people?", "What is it about machines that worries you?"); + $replies[27] = ( "Do you sometimes feel uneasy without a smartphone?", "Have you had these phantasies before?", "Does the world seem more real for you via apps?"); + $replies[28] = ( "Tell me more about your family.", "Who else in your family*?", "What does family relations mean for you?", "Come on, How old are you?"); + @setupReplies = @replies; + + return $setupReplies; +} +# Concept and lisp implementation published by Joseph Weizenbaum (MIT): +# "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +# Computational Linguistis 1(1966)9, pp. 36-45 +# Revision history: +# 2016-10-06 Initial version +# 2017-03-29 Two diagrams updated (comments translated to English) +# 2017-03-29 More keywords and replies added +# 2019-03-14 Replies and mapping reorganised for easier maintenance +# 2019-03-15 key map joined from keyword array and index map +# 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +# 2019-11-28 New global type "History" (to ensure a homogenous array) + +my $varPart; +my $userInput; +my $replyRing; +my $reply; +my @replies; +my @reflexions; +my $posAster; +my @offsets; +my @keyMap; +my $keyIndex; +my $isRepeated; +my $isGone; +my $history; +my @findInfo; +my $entry; +my @byePhrases; + +# Title information +print "************* ELIZA **************", "\n"; +print "* Original design by J. Weizenbaum", "\n"; +print "**********************************", "\n"; +print "* Adapted for Basic on IBM PC by", "\n"; +print "* - Patricia Danielson", "\n"; +print "* - Paul Hashfield", "\n"; +print "**********************************", "\n"; +print "* Adapted for Structorizer by", "\n"; +print "* - Kay Gürtzig / FH Erfurt 2016", "\n"; +print "* Version: 2.3 (2019-11-28)", "\n"; +print "* (Requires at least Structorizer 3.30-03 to run)", "\n"; +print "**********************************", "\n"; +# Stores the last five inputs of the user in a ring buffer, +# the second component is the rolling (over-)write index. +$history = History(("", "", "", "", ""), 0); +@replies = setupReplies(); +@reflexions = setupReflexions(); +@byePhrases = setupGoodByePhrases(); +@keyMap = setupKeywords(); +$offsets[length(@keyMap)-1] = 0; +$isGone = false; +# Starter +print "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?", "\n"; + +do { + chomp($userInput = ); + # Converts the input to lowercase, cuts out interpunctation + # and pads the string + $userInput = normalizeInput($userInput); + $isGone = checkGoodBye($userInput, \@byePhrases); + + if ( ! $isGone ) { + $reply = "Please don\'t repeat yourself!"; + $isRepeated = checkRepetition(\$history, $userInput); + + if ( ! $isRepeated ) { + @findInfo = findKeyword(\@keyMap, $userInput); + $keyIndex = $findInfo[0]; + + if ( $keyIndex < 0 ) { + # Should never happen... + $keyIndex = length(@keyMap)-1; + } + + var $entry: KeyMapEntry = $keyMap[$keyIndex]; + # Variable part of the reply + $varPart = ""; + + if ( length($entry->keyword) > 0 ) { + $varPart = conjugateStrings($userInput, \$entry->keyword, $findInfo[1], \@reflexions); + } + + $replyRing = $replies[$entry->index]; + $reply = $replyRing[$offsets[$keyIndex]]; + $offsets[$keyIndex] = ($offsets[$keyIndex] + 1) % length($replyRing); + $posAster = pos("*", $reply); + + if ( $posAster > 0 ) { + + if ( $varPart == " " ) { + $reply = "You will have to elaborate more for me to help you."; + } + else { + delete($reply, $posAster, 1); + insert($varPart, $reply, $posAster); + } + + } + + $reply = adjustSpelling($reply); + } + + print $reply, "\n"; + } + +} while (!( $isGone )); + diff --git a/samples/export/Perl/SORTING_TEST_MAIN.pl b/samples/export/Perl/SORTING_TEST_MAIN.pl index 68b88527..ab77a6af 100644 --- a/samples/export/Perl/SORTING_TEST_MAIN.pl +++ b/samples/export/Perl/SORTING_TEST_MAIN.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -# Generated by Structorizer 3.30-02 +# Generated by Structorizer 3.30-03 # # Copyright (C) 2019-10-02 Kay Gürtzig # License: GPLv3-link @@ -10,6 +10,7 @@ use strict; use warnings; +use Class::Struct; use threads; use threads::shared; @@ -27,7 +28,7 @@ sub bubbleSort { my $i; my $ende; - $ende = length($values) - 2; + $ende = length(@$values) - 2; do { # The index of the most recent swapping (-1 means no swapping done). @@ -35,10 +36,10 @@ sub bubbleSort { for ($i = 0; $i <= $ende; $i += (1)) { - if ( $values[$i] > $values[$i+1] ) { - $temp = $values[$i]; - $values[$i] = $values[$i+1]; - $values[$i+1] = $temp; + if ( $$values[$i] > $$values[$i+1] ) { + $temp = $$values[$i]; + $$values[$i] = $$values[$i+1]; + $$values[$i+1] = $temp; $posSwapped = $i; } @@ -69,21 +70,21 @@ sub maxHeapify { # Index of the (local) maximum $max = $i; - if ( $left < $range && $heap[$left] > $heap[$i] ) { + if ( $left < $range && $$heap[$left] > $$heap[$i] ) { $max = $left; } - if ( $right < $range && $heap[$right] > $heap[$max] ) { + if ( $right < $range && $$heap[$right] > $$heap[$max] ) { $max = $right; } if ( $max != $i ) { - $temp = $heap[$i]; - $heap[$i] = $heap[$max]; - $heap[$max] = $temp; - maxHeapify($heap, $max, $range); + $temp = $$heap[$i]; + $$heap[$i] = $$heap[$max]; + $$heap[$max] = $temp; + maxHeapify(\@$heap, $max, $range); } } @@ -105,10 +106,10 @@ sub partition { my $seen; my $pivot; - $pivot = $values[$p]; + $pivot = $$values[$p]; # Tausche das Pivot-Element an den start - $values[$p] = $values[$start]; - $values[$start] = $pivot; + $$values[$p] = $$values[$start]; + $$values[$start] = $pivot; $p = $start; # Beginning and end of the remaining unknown range $start = $start + 1; @@ -116,19 +117,19 @@ sub partition { # Still unseen elements? while ( $stop >= $start ) { - $seen = $values[$start]; + $seen = $$values[$start]; - if ( $values[$start] <= $pivot ) { + if ( $$values[$start] <= $pivot ) { # Swap pivot element with start element - $values[$p] = $seen; - $values[$start] = $pivot; + $$values[$p] = $seen; + $$values[$start] = $pivot; $p = $p + 1; $start = $start + 1; } else { # Put the found element to the end of the unknown area - $values[$start] = $values[$stop]; - $values[$stop] = $seen; + $$values[$start] = $$values[$stop]; + $$values[$stop] = $seen; $stop = $stop - 1; } @@ -211,7 +212,7 @@ sub quickSort { { # ----------------- START THREAD 0 ----------------- - my $thr3dfab37d_0 = threads->create(sub { + my $thr7fed1521_0 = threads->create(sub { my $values = $_[0]; my $start = $_[1]; my $p = $_[2]; @@ -221,7 +222,7 @@ sub quickSort { # ----------------- START THREAD 1 ----------------- - my $thr3dfab37d_1 = threads->create(sub { + my $thr7fed1521_1 = threads->create(sub { my $values = $_[0]; my $p = $_[1]; my $stop = $_[2]; @@ -231,11 +232,11 @@ sub quickSort { # ----------------- AWAIT THREAD 0 ----------------- - $thr3dfab37d_0->join(); + $thr7fed1521_0->join(); # ----------------- AWAIT THREAD 1 ----------------- - $thr3dfab37d_1->join(); + $thr7fed1521_1->join(); } # ========================================================== @@ -257,16 +258,16 @@ sub heapSort { my $k; my $heapRange; - buildMaxHeap($values); - $heapRange = length($values); + buildMaxHeap(\@$values); + $heapRange = length(@$values); for ($k = $heapRange - 1; $k >= 1; $k += (-1)) { $heapRange = $heapRange - 1; # Swap the maximum value (root of the heap) to the heap end - $maximum = $values[0]; - $values[0] = $values[$heapRange]; - $values[$heapRange] = $maximum; - maxHeapify($values, 0, $heapRange); + $maximum = $$values[0]; + $$values[0] = $$values[$heapRange]; + $$values[$heapRange] = $maximum; + maxHeapify(\@$values, 0, $heapRange); } @@ -277,9 +278,9 @@ sub heapSort { # sensibly be switched on). # Requested input data are: Number of elements (size) and filing mode. -my $values3; -my $values2; -my $values1; +my @values3; +my @values2; +my @values1; my $show; my $ok3; my $ok2; @@ -319,7 +320,7 @@ sub heapSort { } -# Kopiere das Array für exakte Vergleichbarkeit +# Copy the array for exact comparability for ($i = 0; $i <= $elementCount-1; $i += (1)) { $values2[$i] = $values1[$i]; $values3[$i] = $values1[$i]; @@ -333,46 +334,46 @@ sub heapSort { { # ----------------- START THREAD 0 ----------------- - my $thr4f085546_0 = threads->create(sub { + my $thr110a6988_0 = threads->create(sub { my $values1 = $_[0]; - bubbleSort($values1); - }, ($values1)); + bubbleSort(\@values1); + }, (\@values1)); # ----------------- START THREAD 1 ----------------- - my $thr4f085546_1 = threads->create(sub { + my $thr110a6988_1 = threads->create(sub { my $values2 = $_[0]; my $elementCount = $_[1]; - quickSort($values2, 0, $elementCount); - }, ($values2, $elementCount)); + quickSort(\@values2, 0, $elementCount); + }, (\@values2, $elementCount)); # ----------------- START THREAD 2 ----------------- - my $thr4f085546_2 = threads->create(sub { + my $thr110a6988_2 = threads->create(sub { my $values3 = $_[0]; - heapSort($values3); - }, ($values3)); + heapSort(\@values3); + }, (\@values3)); # ----------------- AWAIT THREAD 0 ----------------- - $thr4f085546_0->join(); + $thr110a6988_0->join(); # ----------------- AWAIT THREAD 1 ----------------- - $thr4f085546_1->join(); + $thr110a6988_1->join(); # ----------------- AWAIT THREAD 2 ----------------- - $thr4f085546_2->join(); + $thr110a6988_2->join(); } # ========================================================== # ================== END PARALLEL SECTION ================== # ========================================================== -$ok1 = testSorted($values1); -$ok2 = testSorted($values2); -$ok3 = testSorted($values3); +$ok1 = testSorted(\@values1); +$ok2 = testSorted(\@values2); +$ok3 = testSorted(\@values3); if ( ! $ok1 || ! $ok2 || ! $ok3 ) { diff --git a/samples/export/Perl/TextDemo.pl b/samples/export/Perl/TextDemo.pl new file mode 100644 index 00000000..51e134e7 --- /dev/null +++ b/samples/export/Perl/TextDemo.pl @@ -0,0 +1,1279 @@ +#!/usr/bin/perl +# Generated by Structorizer 3.30-03 +# +# Copyright (C) 2019-10-10 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# + +use strict; +use warnings; +use Class::Struct; + +# Draws a blank for font height h, ignoring the colorNo +sub blank { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + + $width = $h/2.0; + penUp(); + right(90); + forward($width); # color = ffffff + left(90); +} + +sub forward { + my $len = $_[0]; + my $color = $_[1]; + + + + switch ( $color ) { + + case (1) { + forward($len); # color = ffffff + } + + case (2) { + forward($len); # color = ff8080 + } + + case (3) { + forward($len); # color = ffff80 + } + + case (4) { + forward($len); # color = 80ff80 + } + + case (5) { + forward($len); # color = 80ffff + } + + case (6) { + forward($len); # color = 0080ff + } + + case (7) { + forward($len); # color = ff80c0 + } + + case (8) { + forward($len); # color = c0c0c0 + } + + case (9) { + forward($len); # color = ff8000 + } + + case (10) { + forward($len); # color = 8080ff + } + } + +} + +# Draws letter A in colour specified by colorNo with font height h +# from the current turtle position. +sub letterA { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $hypo = sqrt($h*$h + $width*$width/4.0); + $rotAngle = toDegrees(atan($width/2.0/$h)); + right($rotAngle); + forward($hypo/2.0, $colorNo); + right(90 - $rotAngle); + forward($width/2.0, $colorNo); + penUp(); + backward($width/2.0); # color = ffffff + penDown(); + left(90 - $rotAngle); + forward($hypo/2.0, $colorNo); + left(2*$rotAngle); + forward(-$hypo, $colorNo); + right($rotAngle); +} + +# Draws letter E in colour specified by colorNo with font height h +# from the current turtle position. +sub letterE { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + + $width = $h/2.0; + forward($h, $colorNo); + right(90); + forward($width, $colorNo); + right(90); + penUp(); + forward($h/2.0); # color = ffffff + right(90); + penDown(); + forward($width, $colorNo); + left(90); + penUp(); + forward($h/2.0); # color = ffffff + left(90); + penDown(); + forward($width, $colorNo); + left(90); +} + +# Draws letter F in colour specified by colorNo with font height h +# from the current turtle position. +sub letterF { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + + $width = $h/2.0; + forward($h, $colorNo); + right(90); + forward($width, $colorNo); + right(90); + penUp(); + forward($h/2.0); # color = ffffff + right(90); + penDown(); + forward($width, $colorNo); + left(90); + penUp(); + forward($h/2.0); # color = ffffff + left(90); + forward($width); # color = ffffff + penDown(); + left(90); +} + +# Draws letter H in colour specified by colorNo with font height h +# from the current turtle position. +sub letterH { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + + $width = $h/2.0; + forward($h, $colorNo); + penUp(); + right(90); + forward($width); # color = ffffff + right(90); + penDown(); + forward($h/2.0, $colorNo); + right(90); + forward($width, $colorNo); + penUp(); + backward($width); # color = ffffff + left(90); + penDown(); + forward($h/2.0, $colorNo); + left(180); +} + +# Draws letter I in colour specified by colorNo with font height h +# from the current turtle position. +sub letterI { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $c; + my $b; + + # Octagon edge length + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Cathetus of the corner triangle outside the octagon + $c = $b / sqrt(2.0); + penUp(); + right(90); + forward($c); # color = ffffff + penDown(); + forward($b, $colorNo); + penUp(); + backward($b/2.0); # color = ffffff + left(90); + penDown(); + forward($h, $colorNo); + penUp(); + right(90); + backward($b/2.0); # color = ffffff + penDown(); + forward($b, $colorNo); + penUp(); + forward($b/2 + $c); # color = ffffff + left(90); + backward($h); # color = ffffff + penDown(); +} + +# Draws letter K in colour specified by colorNo with font height h +# from the current turtle position. +sub letterK { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $diag; + + $width = $h/2.0; + $diag = $h/sqrt(2.0); + forward($h, $colorNo); + penUp(); + right(90); + forward($width); # color = ffffff + right(135); + penDown(); + forward($diag, $colorNo); + left(90); + forward($diag, $colorNo); + left(135); +} + +# Draws letter L in colour specified by colorNo with font height h +# from the current turtle position. +sub letterL { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + + $width = $h/2.0; + forward($h, $colorNo); + penUp(); + backward($h); # color = ffffff + right(90); + penDown(); + forward($width, $colorNo); + left(90); +} + +# Draws letter M in colour specified by colorNo with font height h +# from the current turtle position. +sub letterM { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $hypo = sqrt($width*$width + $h*$h)/2.0; + $rotAngle = toDegrees(atan($width/$h)); + forward($h, $colorNo); + left($rotAngle); + forward(-$hypo, $colorNo); + right(2*$rotAngle); + forward($hypo, $colorNo); + left($rotAngle); + forward(-$h, $colorNo); +} + +# Draws letter N in colour specified by colorNo with font height h +# from the current turtle position. +sub letterN { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $hypo = sqrt($width*$width + $h*$h); + $rotAngle = toDegrees(atan($width/$h)); + forward($h, $colorNo); + left($rotAngle); + forward(-$hypo, $colorNo); + right($rotAngle); + forward($h, $colorNo); + penUp(); + backward($h); # color = ffffff + penDown(); +} + +# Draws letter T in colour specified by colorNo with font height h +# from the current turtle position. +sub letterT { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + + $width = $h/2.0; + penUp(); + forward($h); # color = ffffff + penDown(); + right(90); + forward($width, $colorNo); + penUp(); + backward($width/2.0); # color = ffffff + penDown(); + right(90); + forward($h, $colorNo); + left(90); + penUp(); + forward($width/2.0); # color = ffffff + penDown(); + left(90); +} + +# Draws letter V in colour specified by colorNo with font height h +# from the current turtle position. +sub letterV { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $hypo = sqrt($h*$h + $width*$width/4.0); + $rotAngle = toDegrees(atan($width/2.0/$h)); + penUp(); + forward($h); # color = ffffff + left($rotAngle); + penDown(); + forward(-$hypo, $colorNo); + right(2*$rotAngle); + forward($hypo, $colorNo); + penUp(); + left($rotAngle); + backward($h); # color = ffffff + penDown(); +} + +# Draws letter W in colour specified by colorNo with font height h +# from the current turtle position. +sub letterW { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width_3; + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $width_3 = $width/3.0; + $hypo = sqrt($width_3*$width_3 + $h*$h); + $rotAngle = toDegrees(atan($width_3/$h)); + penUp(); + forward($h); # color = ffffff + left($rotAngle); + penDown(); + forward(-$hypo, $colorNo); + right(2*$rotAngle); + forward($hypo, $colorNo); + penUp(); + left(90+$rotAngle); + forward($width_3); # color = ffffff + right(90-$rotAngle); + penDown(); + forward(-$hypo, $colorNo); + right(2*$rotAngle); + forward($hypo, $colorNo); + penUp(); + left($rotAngle); + backward($h); # color = ffffff + penDown(); +} + +# Draws letter X in colour specified by colorNo with font height h +# from the current turtle position. +sub letterX { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $hypo = sqrt($width*$width + $h*$h); + $rotAngle = toDegrees(atan($width/$h)); + right($rotAngle); + forward($hypo, $colorNo); + penUp(); + left(90+$rotAngle); + forward($width); # color = ffffff + right(90-$rotAngle); + penDown(); + forward(-$hypo, $colorNo); + right($rotAngle); +} + +# Draws letter Y in colour specified by colorNo with font height h +# from the current turtle position. +sub letterY { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $hypo = sqrt($width*$width + $h*$h)/2.0; + $rotAngle = toDegrees(atan($width/$h)); + penUp(); + forward($h); # color = ffffff + left($rotAngle); + penDown(); + forward(-$hypo, $colorNo); + right($rotAngle); + penUp(); + backward($h/2.0); # color = ffffff + penDown(); + forward($h/2.0, $colorNo); + right($rotAngle); + forward($hypo, $colorNo); + left($rotAngle); + penUp(); + backward($h); # color = ffffff + penDown(); +} + +# Draws letter Z in colour specified by colorNo with font height h +# from the current turtle position. +sub letterZ { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle; + my $hypo; + + $width = $h/2.0; + $hypo = sqrt($width*$width + $h*$h); + $rotAngle = toDegrees(atan($width/$h)); + penUp(); + forward($h); # color = ffffff + right(90); + penDown(); + forward($width, $colorNo); + left(90-$rotAngle); + forward(-$hypo, $colorNo); + right(90-$rotAngle); + forward($width, $colorNo); + left(90); +} + +# Draws nEdges edges of a regular n-polygon with edge length a +# counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +sub polygonPart { + my $a = $_[0]; + my $n = $_[1]; + my $ctrclkws = $_[2]; + my $nEdges = $_[3]; + my $color = $_[4]; + + my $rotAngle; + my $k; + + $rotAngle = 360.0/$n; + + if ( $ctrclkws ) { + $rotAngle = -$rotAngle; + } + + + for ($k = 1; $k <= $nEdges; $k += (1)) { + right($rotAngle); + forward($a, $color); + } + +} + +# Draws a dummy character (small centered square) with font height h and +# the colour encoded by colorNo +sub charDummy { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $d; + my $c; + my $b; + + $width = $h / 2.0; + # Octagon edge length (here: edge lengzh of the square) + $b = $width / (sqrt(2.0) + 1); + # Cathetus of the corner triangle outside the octagon + $c = ($width - $b) / 2.0; + $d = $b / sqrt(2.0); + penUp(); + forward($h/2.0-$b/2.0); # color = ffffff + right(90); + forward($c); # color = ffffff + right(90); + penDown(); + # Draws the square with edge length b + polygonPart($b, 4, true, 4, $colorNo); + penUp(); + left(90); + forward($b + $c); # color = ffffff + left(90); + backward($h/2.0-$b/2.0); # color = ffffff + penDown(); +} + +# Draws a comma in colour specified by colorNo with font height h +# from the current turtle position. +sub comma { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $hypo; + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + $rotAngle = toDegrees(atan(0.5)); + $hypo = $c * sqrt(1.25); + penUp(); + right(90); + forward(($c+$b)/2.0 + $c); # color = ffffff + penDown(); + # Counterclockwise draw 3 edges of a square with edge length c + # in the colour endcoded by colorNo + polygonPart($c, 4, true, 3, $colorNo); + left(90); + forward($c/2.0, $colorNo); + right(90); + forward($c, $colorNo); + left(180 - $rotAngle); + forward($hypo, $colorNo); + penUp(); + right(90 - $rotAngle); + forward(($c + $b)/2.0); # color = ffffff + left(90); + penDown(); +} + +# Draws an exclamation mark in the colour encoded by colorNo with font height h +# from the current turtle position. +sub exclMk { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $width; + my $rotAngle2; + my $rotAngle; + my $length2; + my $length1; + my $hypo; + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + $width = $h/2.0; + $length1 = $h - ($b+$c)/2.0; + $length2 = $length1 - 2*$c; + $hypo = sqrt($width*$width/16.0 + $length2*$length2); + # 360°/8 + $rotAngle = 45; + $rotAngle2 = toDegrees(atan($width/4.0/$length2)); + penUp(); + forward($length1); # color = ffffff + right(90); + forward($width/2.0); # color = ffffff + left(90 + $rotAngle); + penDown(); + # Clockwise draw 5 edges of an octagon with edge length b/2 + # in the colour endcoded by colorNo + polygonPart($b/2.0, 8, false, 5, $colorNo); + right($rotAngle2); + forward($hypo, $colorNo); + left(2*$rotAngle2); + forward(-$hypo, $colorNo); + penUp(); + forward($hypo); # color = ffffff + right($rotAngle2); + forward($c); # color = ffffff + left(90); + forward($c/2.0); # color = ffffff + penDown(); + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart($c, 4, false, 4, $colorNo); + penUp(); + forward(($c + $b)/2.0); # color = ffffff + left(90); + backward($c); # color = ffffff + penDown(); +} + +# Draws a full stop in colour specified by colorNo with font height h +# from the current turtle position. +sub fullSt { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + penUp(); + right(90); + forward(($c+$b)/2.0 + $c); # color = ffffff + penDown(); + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart($c, 4, true, 4, $colorNo); + penUp(); + forward(($c + $b)/2.0); # color = ffffff + left(90); + penDown(); +} + +# Draws letter B in colour specified by colorNo with font height h +# from the current turtle position. +sub letterB { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $c; + my $b; + + # Octagon edge length + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Cathetus of the outer corner triangle of the octagon + $c = $b / sqrt(2.0); + forward($h, $colorNo); + right(90); + forward($c+$b, $colorNo); + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart($b, 8, false, 4, $colorNo); + forward($c, $colorNo); + penUp(); + left(180); + forward($b + $c); # color = ffffff + penDown(); + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart($b, 8, false, 4, $colorNo); + forward($c, $colorNo); + penUp(); + left(180); + forward($b + 2*$c); # color = ffffff + penDown(); + left(90); +} + +# Draws letter C in the colour encoded by colorNo with font height h +# from the current turtle position. +sub letterC { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $c; + my $b; + + # Octagon edge length + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Cathetus of the outer trinagle at the octagon corner + $c = $b / sqrt(2.0); + # 360°/8 + $rotAngle = 45; + penUp(); + forward($c); # color = ffffff + penDown(); + right(180); + # Clockwise draws 3 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart($b, 8, true, 3, $colorNo); + left($rotAngle); + penUp(); + forward(2*$b + 2*$c); # color = ffffff + penDown(); + # Counterclockwise draws 4 edges of an octagon with edge length b + # iin the colour encoded by colorNo + polygonPart($b, 8, true, 4, $colorNo); + forward($b + 2*$c, $colorNo); + penUp(); + forward($c); # color = ffffff + left(90); + forward($b + 2*$c, $colorNo); + penDown(); + left(90); +} + +# Draws letter D in colour specified by colorNo with font height h +# from the current turtle position. +sub letterD { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + forward($h, $colorNo); + right(90); + forward($c+$b, $colorNo); + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart($b, 8, false, 2, $colorNo); + forward($b + 2*$c, $colorNo); + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart($b, 8, false, 2, $colorNo); + forward($c, $colorNo); + penUp(); + left(180); + forward($b + 2*$c); # color = ffffff + penDown(); + left(90); +} + +# Draws letter G in colour specified by colorNo with font height h +# from the current turtle position. +sub letterG { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $c; + my $b; + + # Octagon edge length + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Cathetus of the corner triangle outside the octagon. + $c = $b / sqrt(2.0); + penUp(); + forward($c); # color = ffffff + penDown(); + right(180); + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart($b, 8, true, 4, $colorNo); + forward($c, $colorNo); + left(90); + forward($b/2.0 + $c, $colorNo); + penUp(); + backward($b/2.0 + $c); # color = ffffff + right(90); + forward($b + $c); # color = ffffff + penDown(); + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart($b, 8, true, 4, $colorNo); + forward($b + 2*$c, $colorNo); + penUp(); + forward($c); # color = ffffff + left(90); + forward($b + 2*$c, $colorNo); + penDown(); + left(90); +} + +# Draws letter J in colour encoded by colorNo with font height h +# from the current turtle position. +sub letterJ { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + # 360°/8 + $rotAngle = 45; + penUp(); + forward($c); # color = ffffff + penDown(); + right(180); + # Counterclockwise draw 3 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart($b, 8, true, 3, $colorNo); + left($rotAngle); + forward($h - $c, $colorNo); + penUp(); + backward($h); # color = ffffff + penDown(); +} + +# Draws letter O in colour specified by colorNo with font height h +# from the current turtle position. +sub letterO { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $c; + my $b; + + # Octagon edge length + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Cathetus of the corner triangle outside the octagon + $c = $b / sqrt(2.0); + penUp(); + forward($c); # color = ffffff + penDown(); + right(180); + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, true, 4, $colorNo); + forward($b + 2*$c, $colorNo); + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, true, 4, $colorNo); + forward($b + 2*$c, $colorNo); + penUp(); + forward($c); # color = ffffff + left(90); + forward($b + 2*$c); # color = ffffff + penDown(); + left(90); +} + +# Draws letter P in colour specified by colorNo with font height h +# from the current turtle position. +sub letterP { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $c; + my $b; + + # Octagon edge length + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Cathetus of the corner triangle outside the octagon + $c = $b / sqrt(2.0); + forward($h, $colorNo); + right(90); + forward($c+$b, $colorNo); + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, false, 4, $colorNo); + forward($c, $colorNo); + penUp(); + backward($b + 2*$c); # color = ffffff + left(90); + forward($b + 2*$c); # color = ffffff + penDown(); + left(180); +} + +# Draws letter Q in colour specified by colorNo with font height h +# from the current turtle position. +sub letterQ { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + # 360°/8 + $rotAngle = 45; + penUp(); + forward($c); # color = ffffff + penDown(); + right(180); + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, true, 4, $colorNo); + forward($b + 2*$c, $colorNo); + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, true, 4, $colorNo); + forward($b + 2*$c, $colorNo); + penUp(); + forward($c); # color = ffffff + left(90); + forward($b + 2*$c); # color = ffffff + right($rotAngle); + backward($b); # color = ffffff + penDown(); + forward($b, $colorNo); + left(90 + $rotAngle); +} + +# Zeichnet den Buchstaben R von der Turtleposition aus +# mit Zeilenhöhe h +sub letterR { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + # 360°/8 + $rotAngle = 45; + forward($h, $colorNo); + right(90); + forward($c+$b, $colorNo); + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, false, 4, $colorNo); + forward($c, $colorNo); + left(90 + $rotAngle); + forward(sqrt(2.0)*($b + 2*$c), $colorNo); + left(90 + $rotAngle); +} + +# Draws letter S in colour specified by colorNo with font height h +# from the current turtle position. +sub letterS { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + # 360°/8 + $rotAngle = 45; + penUp(); + forward($c); # color = ffffff + penDown(); + right(180); + # Counterclockwise draw 6 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, true, 6, $colorNo); + # Clockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, false, 5, $colorNo); + right($rotAngle); + penUp(); + forward(2*$b + 3*$c); # color = ffffff + penDown(); + left(180); +} + +# Draws letter U in colour specified by colorNo with font height h +# from the current turtle position. +sub letterU { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $c; + my $b; + + # edge length of a regular octagon + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + # 360°/8 + $rotAngle = 45; + penUp(); + forward($c); # color = ffffff + penDown(); + forward($h - $c, $colorNo); + penUp(); + backward($h-$c); # color = ffffff + penDown(); + right(180); + # Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart($b, 8, true, 3, $colorNo); + left($rotAngle); + forward($h - $c, $colorNo); + penUp(); + backward($h); # color = ffffff + penDown(); +} + +# Draws a question mark in colour specified by colorNo with font height h +# from the current turtle position. +sub qstnMk { + my $h = $_[0]; + my $colorNo = $_[1]; + + my $rotAngle; + my $c; + my $b; + + # Achteck-Kantenlänge + $b = $h * 0.5 / (sqrt(2.0) + 1); + # Eckenlänge außen am Achteck + $c = $b / sqrt(2.0); + # 360°/8 + $rotAngle = 45; + penUp(); + forward($h-$c); # color = ffffff + penDown(); + # Counterclockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart($b, 8, false, 5, $colorNo); + forward($c, $colorNo); + left($rotAngle); + forward($b/2.0, $colorNo); + penUp(); + forward($c); # color = ffffff + left(90); + forward($c/2.0); # color = ffffff + penDown(); + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart($c, 4, false, 4, $colorNo); + penUp(); + forward(($c + $b)/2.0); # color = ffffff + left(90); + backward($c); # color = ffffff + penDown(); +} + +# Has the turtle draw the given string 'text´ with font height 'h´ (in +# pixels) and the colour coded by integer 'c´ from the current Turtle +# position to the Turtle canvas. If the turtle looks North then +# the text will be written rightwards. In the event, the turtle will be +# placed behind the text in original orientation (such that the next text +# would be written like a continuation. Colour codes: +# 1 = black +# 2 = red +# 3 = yellow +# 4 = green +# 5 = cyan +# 6 = blue +# 7 = pink +# 8 = grey +# 9 = orange +# 10 = violet +# All letters (ASCII) will be converted to uppercase, digits cannot +# be represented, the set of representable special characters is: +# '.', ',', '!', '?'. Other characters will be shown as a small +# centred square (dummy character). +sub drawText { + my $text = $_[0]; + my $h = $_[1]; + my $c = $_[2]; + + my $letter; + my $k; + my $gap; + + $gap = $h/10.0; + + for ($k = 1; $k <= length($text); $k += (1)) { + $letter = uppercase(copy($text, $k, 1)); + + if ( $letter == "," ) { + comma($h,$c); + } + else { + + # "," cannot be chacked against because the comma is misinterpreted + # as selector list separator. + switch ( $letter ) { + + case ("A") { + letterA($h,$c); + } + + case ("B") { + letterB($h,$c); + } + + case ("C") { + letterC($h,$c); + } + + case ("D") { + letterD($h,$c); + } + + case ("E") { + letterE($h,$c); + } + + case ("F") { + letterF($h,$c); + } + + case ("G") { + letterG($h,$c); + } + + case ("H") { + letterH($h,$c); + } + + case ("I") { + letterI($h,$c); + } + + case ("J") { + letterJ($h,$c); + } + + case ("K") { + letterK($h,$c); + } + + case ("L") { + letterL($h,$c); + } + + case ("M") { + letterM($h,$c); + } + + case ("N") { + letterN($h,$c); + } + + case ("O") { + letterO($h,$c); + } + + case ("P") { + letterP($h,$c); + } + + case ("Q") { + letterQ($h,$c); + } + + case ("R") { + letterR($h,$c); + } + + case ("S") { + letterS($h,$c); + } + + case ("T") { + letterT($h,$c); + } + + case ("U") { + letterU($h,$c); + } + + case ("V") { + letterV($h,$c); + } + + case ("W") { + letterW($h,$c); + } + + case ("X") { + letterX($h,$c); + } + + case ("Y") { + letterY($h,$c); + } + + case ("Z") { + letterZ($h,$c); + } + + case (" ") { + blank($h,$c); + } + + case ("!") { + exclMk($h,$c); + } + + case ("?") { + qstnMk($h,$c); + } + + case (".") { + fullSt($h,$c); + } + + else { + charDummy($h,$c); + } + } + + } + + right(90); + penUp(); + forward($gap); # color = ffffff + penDown(); + left(90); + } + +} +# Demo program for routine drawText() +# Asks the user to enter a text, a wanted text height and colour, +# and then draws this string onto the turtle screen. Places every +# entered text to a new line. + +my $y; +my $text; +my $height; +my $colour; + +print "This is a demo program for text writing with Turleizer.", "\n"; +showTurtle(); +penDown(); +$y = 0; + +do { + print "Enter some text (empty string to exit)"; chomp($text = ); + # Make sure the content is interpreted as string + $text = "" + $text; + + if ( $text != "" ) { + + do { + print "Height of the text (pixels)"; chomp($height = ); + } while (!( $height >= 5 )); + + + do { + print "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)"; chomp($colour = ); + } while (!( $colour >= 1 && $colour <= 10 )); + + $y = $y + $height + 2; + gotoXY(0, $y - 2); + drawText($text, $height, $colour); + } + +} while (!( $text == "" )); + +gotoXY(0, $y + 15); +drawText("Thank you, bye.", 10, 4); +hideTurtle(); diff --git a/samples/export/Python/ELIZA_2.3.py b/samples/export/Python/ELIZA_2.3.py new file mode 100644 index 00000000..4feedcf7 --- /dev/null +++ b/samples/export/Python/ELIZA_2.3.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ELIZA +# generated by Structorizer 3.30-03 +# +# Copyright (C) 2018-05-14 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# +# You should have installed module recordtype: pip install recordtype +# See https://pypi.org/project/recordtype +from recordtype import recordtype +from enum import Enum +import math +# BEGIN (global) code from included diagram "History" +# histArray contains the most recent user replies as ring buffer; +# histIndex is the index where the next reply is to be stored (= index of the oldest +# cached user reply). +# Note: The depth of the history is to be specified by initializing a variable of this type, +# e.g. for a history of depth 5: +# myhistory <- History{{"", "", "", "", ""}, 0} +History = recordtype("History" "histArray histIndex") +# END (global) code from included diagram "History" +# BEGIN (global) code from included diagram "KeyMapEntry" +# Associates a key word in the text with an index in the reply ring array +KeyMapEntry = recordtype("KeyMapEntry" "keyword index") +# END (global) code from included diagram "KeyMapEntry" + + +# Cares for correct letter case among others +def adjustSpelling(sentence) : + result = sentence + position = 1 + while ((position <= length(sentence)) and (copy(sentence, position, 1) == " ")): + position = position + 1 + + if (position <= length(sentence)): + start = copy(sentence, 1, position) + delete(result, 1, position) + insert(uppercase(start), result, 1) + + for word in [" i ", " i\'"]: + position = pos(word, result) + while (position > 0): + delete(result, position+1, 1) + insert("I", result, position+1) + position = pos(word, result) + + + return result + +# Checks whether the given text contains some kind of +# good-bye phrase inducing the end of the conversation +# and if so writes a correspding good-bye message and +# returns true, otherwise false +def checkGoodBye(text, phrases) : + for pair in phrases: + if (pos(pair[0], text) > 0): + saidBye = true + print(pair[1], sep='') + return true + + return false + +# Checks whether newInput has occurred among the recently cached +# input strings in the histArray component of history and updates the history. +def checkRepetition(history, newInput) : + global History + hasOccurred = false + if (length(newInput) > 4): + histDepth = length(history.histArray) + for i in range(0, histDepth-1+1, 1): + if (newInput == history.histArray[i]): + hasOccurred = true + + history.histArray[history.histIndex] = newInput + history.histIndex = (history.histIndex + 1) % (histDepth) + + return hasOccurred + +def conjugateStrings(sentence, key, keyPos, flexions) : + result = " " + copy(sentence, keyPos + length(key), length(sentence)) + " " + for pair in flexions: + left = "" + right = result + position = pos(pair[0], right) + while (position > 0): + left = left + copy(right, 1, position-1) + pair[1] + right = copy(right, position + length(pair[0]), length(right)) + position = pos(pair[0], right) + + result = left + right + + # Eliminate multiple spaces + position = pos(" ", result) + while (position > 0): + result = copy(result, 1, position-1) + copy(result, position+1, length(result)) + position = pos(" ", result) + + + return result + +# Looks for the occurrence of the first of the strings +# contained in keywords within the given sentence (in +# array order). +# Returns an array of +# 0: the index of the first identified keyword (if any, otherwise -1), +# 1: the position inside sentence (0 if not found) +def findKeyword(keyMap, sentence) : + global KeyMapEntry + # Contains the index of the keyword and its position in sentence + result = [-1, 0] + i = 0 + while ((result[0] < 0) and (i < length(keyMap))): + entry = keyMap[i] + position = pos(entry.keyword, sentence) + if (position > 0): + result[0] = i + result[1] = position + + i = i+1 + + + return result + +# Converts the sentence to lowercase, eliminates all +# interpunction (i.e. ',', '.', ';'), and pads the +# sentence among blanks +def normalizeInput(sentence) : + sentence = lowercase(sentence) + for symbol in ['.', ',', ';', '!', '?']: + position = pos(symbol, sentence) + while (position > 0): + sentence = copy(sentence, 1, position-1) + copy(sentence, position+1, length(sentence)) + position = pos(symbol, sentence) + + result = " " + sentence + " " + + return result + +def setupGoodByePhrases() : + phrases[0] = [" shut", "Okay. If you feel that way I\'ll shut up. ... Your choice."] + phrases[1] = ["bye", "Well, let\'s end our talk for now. See you later. Bye."] + return phrases + +# The lower the index the higher the rank of the keyword (search is sequential). +# The index of the first keyword found in a user sentence maps to a respective +# reply ring as defined in `setupReplies()´. +def setupKeywords() : + global KeyMapEntry + # The empty key string (last entry) is the default clause - will always be found + keywords[39] = KeyMapEntry("", 29) + keywords[0] = KeyMapEntry("can you ", 0) + keywords[1] = KeyMapEntry("can i ", 1) + keywords[2] = KeyMapEntry("you are ", 2) + keywords[3] = KeyMapEntry("you\'re ", 2) + keywords[4] = KeyMapEntry("i don't ", 3) + keywords[5] = KeyMapEntry("i feel ", 4) + keywords[6] = KeyMapEntry("why don\'t you ", 5) + keywords[7] = KeyMapEntry("why can\'t i ", 6) + keywords[8] = KeyMapEntry("are you ", 7) + keywords[9] = KeyMapEntry("i can\'t ", 8) + keywords[10] = KeyMapEntry("i am ", 9) + keywords[11] = KeyMapEntry("i\'m ", 9) + keywords[12] = KeyMapEntry("you ", 10) + keywords[13] = KeyMapEntry("i want ", 11) + keywords[14] = KeyMapEntry("what ", 12) + keywords[15] = KeyMapEntry("how ", 12) + keywords[16] = KeyMapEntry("who ", 12) + keywords[17] = KeyMapEntry("where ", 12) + keywords[18] = KeyMapEntry("when ", 12) + keywords[19] = KeyMapEntry("why ", 12) + keywords[20] = KeyMapEntry("name ", 13) + keywords[21] = KeyMapEntry("cause ", 14) + keywords[22] = KeyMapEntry("sorry ", 15) + keywords[23] = KeyMapEntry("dream ", 16) + keywords[24] = KeyMapEntry("hello ", 17) + keywords[25] = KeyMapEntry("hi ", 17) + keywords[26] = KeyMapEntry("maybe ", 18) + keywords[27] = KeyMapEntry(" no", 19) + keywords[28] = KeyMapEntry("your ", 20) + keywords[29] = KeyMapEntry("always ", 21) + keywords[30] = KeyMapEntry("think ", 22) + keywords[31] = KeyMapEntry("alike ", 23) + keywords[32] = KeyMapEntry("yes ", 24) + keywords[33] = KeyMapEntry("friend ", 25) + keywords[34] = KeyMapEntry("computer", 26) + keywords[35] = KeyMapEntry("bot ", 26) + keywords[36] = KeyMapEntry("smartphone", 27) + keywords[37] = KeyMapEntry("father ", 28) + keywords[38] = KeyMapEntry("mother ", 28) + return keywords + +# Returns an array of pairs of mutualy substitutable +def setupReflexions() : + reflexions[0] = [" are ", " am "] + reflexions[1] = [" were ", " was "] + reflexions[2] = [" you ", " I "] + reflexions[3] = [" your", " my"] + reflexions[4] = [" i\'ve ", " you\'ve "] + reflexions[5] = [" i\'m ", " you\'re "] + reflexions[6] = [" me ", " you "] + reflexions[7] = [" my ", " your "] + reflexions[8] = [" i ", " you "] + reflexions[9] = [" am ", " are "] + return reflexions + +# This routine sets up the reply rings addressed by the key words defined in +# routine `setupKeywords()´ and mapped hitherto by the cross table defined +# in `setupMapping()´ +def setupReplies() : + replies = None # meant to be of type @@String + # We start with the highest index for performance reasons + # (is to avoid frequent array resizing) + replies[29] = [ "Say, do you have any psychological problems?", "What does that suggest to you?", "I see.", "I'm not sure I understand you fully.", "Come come elucidate your thoughts.", "Can you elaborate on that?", "That is quite interesting."] + replies[0] = [ "Don't you believe that I can*?", "Perhaps you would like to be like me?", "You want me to be able to*?"] + replies[1] = [ "Perhaps you don't want to*?", "Do you want to be able to*?"] + replies[2] = [ "What makes you think I am*?", "Does it please you to believe I am*?", "Perhaps you would like to be*?", "Do you sometimes wish you were*?"] + replies[3] = [ "Don't you really*?", "Why don't you*?", "Do you wish to be able to*?", "Does that trouble you*?"] + replies[4] = [ "Do you often feel*?", "Are you afraid of feeling*?", "Do you enjoy feeling*?"] + replies[5] = [ "Do you really believe I don't*?", "Perhaps in good time I will*.", "Do you want me to*?"] + replies[6] = [ "Do you think you should be able to*?", "Why can't you*?"] + replies[7] = [ "Why are you interested in whether or not I am*?", "Would you prefer if I were not*?", "Perhaps in your fantasies I am*?"] + replies[8] = [ "How do you know you can't*?", "Have you tried?","Perhaps you can now*."] + replies[9] = [ "Did you come to me because you are*?", "How long have you been*?", "Do you believe it is normal to be*?", "Do you enjoy being*?"] + replies[10] = [ "We were discussing you--not me.", "Oh, I*.", "You're not really talking about me, are you?"] + replies[11] = [ "What would it mean to you if you got*?", "Why do you want*?", "Suppose you soon got*...", "What if you never got*?", "I sometimes also want*."] + replies[12] = [ "Why do you ask?", "Does that question interest you?", "What answer would please you the most?", "What do you think?", "Are such questions on your mind often?", "What is it that you really want to know?", "Have you asked anyone else?", "Have you asked such questions before?", "What else comes to mind when you ask that?"] + replies[13] = [ "Names don't interest me.", "I don't care about names -- please go on."] + replies[14] = [ "Is that the real reason?", "Don't any other reasons come to mind?", "Does that reason explain anything else?", "What other reasons might there be?"] + replies[15] = [ "Please don't apologize!", "Apologies are not necessary.", "What feelings do you have when you apologize?", "Don't be so defensive!"] + replies[16] = [ "What does that dream suggest to you?", "Do you dream often?", "What persons appear in your dreams?", "Are you disturbed by your dreams?"] + replies[17] = [ "How do you do ...please state your problem."] + replies[18] = [ "You don't seem quite certain.", "Why the uncertain tone?", "Can't you be more positive?", "You aren't sure?", "Don't you know?"] + replies[19] = [ "Are you saying no just to be negative?", "You are being a bit negative.", "Why not?", "Are you sure?", "Why no?"] + replies[20] = [ "Why are you concerned about my*?", "What about your own*?"] + replies[21] = [ "Can you think of a specific example?", "When?", "What are you thinking of?", "Really, always?"] + replies[22] = [ "Do you really think so?", "But you are not sure you*?", "Do you doubt you*?"] + replies[23] = [ "In what way?", "What resemblance do you see?", "What does the similarity suggest to you?", "What other connections do you see?", "Could there really be some connection?", "How?", "You seem quite positive."] + replies[24] = [ "Are you sure?", "I see.", "I understand."] + replies[25] = [ "Why do you bring up the topic of friends?", "Do your friends worry you?", "Do your friends pick on you?", "Are you sure you have any friends?", "Do you impose on your friends?", "Perhaps your love for friends worries you."] + replies[26] = [ "Do computers worry you?", "Are you talking about me in particular?", "Are you frightened by machines?", "Why do you mention computers?", "What do you think machines have to do with your problem?", "Don't you think computers can help people?", "What is it about machines that worries you?"] + replies[27] = [ "Do you sometimes feel uneasy without a smartphone?", "Have you had these phantasies before?", "Does the world seem more real for you via apps?"] + replies[28] = [ "Tell me more about your family.", "Who else in your family*?", "What does family relations mean for you?", "Come on, How old are you?"] + setupReplies = replies + + return setupReplies + +# Concept and lisp implementation published by Joseph Weizenbaum (MIT): +# "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +# Computational Linguistis 1(1966)9, pp. 36-45 +# Revision history: +# 2016-10-06 Initial version +# 2017-03-29 Two diagrams updated (comments translated to English) +# 2017-03-29 More keywords and replies added +# 2019-03-14 Replies and mapping reorganised for easier maintenance +# 2019-03-15 key map joined from keyword array and index map +# 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +# 2019-11-28 New global type "History" (to ensure a homogenous array) +global History +global KeyMapEntry +# Title information +print("************* ELIZA **************", sep='') +print("* Original design by J. Weizenbaum", sep='') +print("**********************************", sep='') +print("* Adapted for Basic on IBM PC by", sep='') +print("* - Patricia Danielson", sep='') +print("* - Paul Hashfield", sep='') +print("**********************************", sep='') +print("* Adapted for Structorizer by", sep='') +print("* - Kay Gürtzig / FH Erfurt 2016", sep='') +print("* Version: 2.3 (2019-11-28)", sep='') +print("* (Requires at least Structorizer 3.30-03 to run)", sep='') +print("**********************************", sep='') +# Stores the last five inputs of the user in a ring buffer, +# the second component is the rolling (over-)write index. +history = History(["", "", "", "", ""], 0) +replies = setupReplies() +reflexions = setupReflexions() +byePhrases = setupGoodByePhrases() +keyMap = setupKeywords() +offsets[length(keyMap)-1] = 0 +isGone = false +# Starter +print("Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?", sep='') +while True: + userInput = input("userInput") + # Converts the input to lowercase, cuts out interpunctation + # and pads the string + userInput = normalizeInput(userInput) + isGone = checkGoodBye(userInput, byePhrases) + if (not isGone): + reply = "Please don\'t repeat yourself!" + isRepeated = checkRepetition(history, userInput) + if (not isRepeated): + findInfo = findKeyword(keyMap, userInput) + keyIndex = findInfo[0] + if (keyIndex < 0): + # Should never happen... + keyIndex = length(keyMap)-1 + + entry = keyMap[keyIndex] + # Variable part of the reply + varPart = "" + if (length(entry.keyword) > 0): + varPart = conjugateStrings(userInput, entry.keyword, findInfo[1], reflexions) + + replyRing = replies[entry.index] + reply = replyRing[offsets[keyIndex]] + offsets[keyIndex] = (offsets[keyIndex] + 1) % length(replyRing) + posAster = pos("*", reply) + if (posAster > 0): + if (varPart == " "): + reply = "You will have to elaborate more for me to help you." + else: + delete(reply, posAster, 1) + insert(varPart, reply, posAster) + + reply = adjustSpelling(reply) + + print(reply, sep='') + + if isGone: + break + diff --git a/samples/export/Python/SORTING_TEST_MAIN.py b/samples/export/Python/SORTING_TEST_MAIN.py index e3864a04..821f71da 100644 --- a/samples/export/Python/SORTING_TEST_MAIN.py +++ b/samples/export/Python/SORTING_TEST_MAIN.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # SORTING_TEST_MAIN -# generated by Structorizer 3.30-02 +# generated by Structorizer 3.30-03 # # Copyright (C) 2019-10-02 Kay Gürtzig # License: GPLv3-link @@ -9,6 +9,10 @@ # https://www.gnu.org/licenses/gpl.html # http://www.gnu.de/documents/gpl.de.html # +# You should have installed module recordtype: pip install recordtype +# See https://pypi.org/project/recordtype +from recordtype import recordtype +from enum import Enum from threading import Thread import math @@ -136,14 +140,14 @@ def quickSort(values, start, stop) : # ========================================================== # ================= START PARALLEL SECTION ================= # ========================================================== - thr3dfab37d_0 = Thread(target=quickSort, args=(p,start,values)) - thr3dfab37d_0.start() + thr7fed1521_0 = Thread(target=quickSort, args=(p,start,values)) + thr7fed1521_0.start() - thr3dfab37d_1 = Thread(target=quickSort, args=(stop,p,values)) - thr3dfab37d_1.start() + thr7fed1521_1 = Thread(target=quickSort, args=(stop,p,values)) + thr7fed1521_1.start() - thr3dfab37d_0.join() - thr3dfab37d_1.join() + thr7fed1521_0.join() + thr7fed1521_1.join() # ========================================================== # ================== END PARALLEL SECTION ================== # ========================================================== @@ -190,7 +194,7 @@ def heapSort(values) : elif ((modus) == 3) : values1[i] = -i -# Kopiere das Array für exakte Vergleichbarkeit +# Copy the array for exact comparability for i in range(0, elementCount-1+1, 1): values2[i] = values1[i] values3[i] = values1[i] @@ -199,18 +203,18 @@ def heapSort(values) : # ========================================================== # ================= START PARALLEL SECTION ================= # ========================================================== -thr4f085546_0 = Thread(target=bubbleSort, args=(values1,)) -thr4f085546_0.start() +thr247e34b9_0 = Thread(target=bubbleSort, args=(values1,)) +thr247e34b9_0.start() -thr4f085546_1 = Thread(target=quickSort, args=(elementCount,values2)) -thr4f085546_1.start() +thr247e34b9_1 = Thread(target=quickSort, args=(elementCount,values2)) +thr247e34b9_1.start() -thr4f085546_2 = Thread(target=heapSort, args=(values3,)) -thr4f085546_2.start() +thr247e34b9_2 = Thread(target=heapSort, args=(values3,)) +thr247e34b9_2.start() -thr4f085546_0.join() -thr4f085546_1.join() -thr4f085546_2.join() +thr247e34b9_0.join() +thr247e34b9_1.join() +thr247e34b9_2.join() # ========================================================== # ================== END PARALLEL SECTION ================== # ========================================================== diff --git a/samples/export/Python/TextDemo.py b/samples/export/Python/TextDemo.py new file mode 100644 index 00000000..a6ea7aca --- /dev/null +++ b/samples/export/Python/TextDemo.py @@ -0,0 +1,1059 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# TextDemo +# generated by Structorizer 3.30-03 +# +# Copyright (C) 2019-10-10 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# +# You should have installed module recordtype: pip install recordtype +# See https://pypi.org/project/recordtype +from recordtype import recordtype +from enum import Enum +import math +import turtle +turtle.colormode(255) +turtle.mode("logo") + +# Draws a blank for font height h, ignoring the colorNo +def blank(h, colorNo) : + width = h/2.0 + turtle.penup() + turtle.right(90) + col12c27fd8 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(width) + turtle.left(90) + turtle.pencolor(col12c27fd8) + +def forward(len, color) : + if ((color) == 1) : + col5866ce84 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(len) + turtle.pencolor(col5866ce84) + elif ((color) == 2) : + col2a90ef04 = turtle.pencolor(); turtle.pencolor("#ff8080") + turtle.forward(len) + turtle.pencolor(col2a90ef04) + elif ((color) == 3) : + col50bac3a2 = turtle.pencolor(); turtle.pencolor("#ffff80") + turtle.forward(len) + turtle.pencolor(col50bac3a2) + elif ((color) == 4) : + col363b90f0 = turtle.pencolor(); turtle.pencolor("#80ff80") + turtle.forward(len) + turtle.pencolor(col363b90f0) + elif ((color) == 5) : + col7b926e02 = turtle.pencolor(); turtle.pencolor("#80ffff") + turtle.forward(len) + turtle.pencolor(col7b926e02) + elif ((color) == 6) : + col7ff697f4 = turtle.pencolor(); turtle.pencolor("#0080ff") + turtle.forward(len) + turtle.pencolor(col7ff697f4) + elif ((color) == 7) : + col7204b75f = turtle.pencolor(); turtle.pencolor("#ff80c0") + turtle.forward(len) + turtle.pencolor(col7204b75f) + elif ((color) == 8) : + col2dff1f1a = turtle.pencolor(); turtle.pencolor("#c0c0c0") + turtle.forward(len) + turtle.pencolor(col2dff1f1a) + elif ((color) == 9) : + col113016a4 = turtle.pencolor(); turtle.pencolor("#ff8000") + turtle.forward(len) + turtle.pencolor(col113016a4) + elif ((color) == 10) : + col49fa0789 = turtle.pencolor(); turtle.pencolor("#8080ff") + turtle.forward(len) + turtle.pencolor(col49fa0789) + + +# Draws letter A in colour specified by colorNo with font height h +# from the current turtle position. +def letterA(h, colorNo) : + width = h/2.0 + hypo = math.sqrt(h*h + width*width/4.0) + rotAngle = math.degrees(math.atan(width/2.0/h)) + turtle.right(rotAngle) + turtle.forward(hypo/2.0, colorNo) + turtle.right(90 - rotAngle) + turtle.forward(width/2.0, colorNo) + turtle.penup() + col6cac552c = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(width/2.0) + turtle.pendown() + turtle.pencolor(col6cac552c) + turtle.left(90 - rotAngle) + turtle.forward(hypo/2.0, colorNo) + turtle.left(2*rotAngle) + turtle.forward(-hypo, colorNo) + turtle.right(rotAngle) + +# Draws letter E in colour specified by colorNo with font height h +# from the current turtle position. +def letterE(h, colorNo) : + width = h/2.0 + turtle.forward(h, colorNo) + turtle.right(90) + turtle.forward(width, colorNo) + turtle.right(90) + turtle.penup() + col547cc0c2 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h/2.0) + turtle.right(90) + turtle.pendown() + turtle.pencolor(col547cc0c2) + turtle.forward(width, colorNo) + turtle.left(90) + turtle.penup() + col589b3035 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h/2.0) + turtle.left(90) + turtle.pendown() + turtle.pencolor(col589b3035) + turtle.forward(width, colorNo) + turtle.left(90) + +# Draws letter F in colour specified by colorNo with font height h +# from the current turtle position. +def letterF(h, colorNo) : + width = h/2.0 + turtle.forward(h, colorNo) + turtle.right(90) + turtle.forward(width, colorNo) + turtle.right(90) + turtle.penup() + col2e050b95 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h/2.0) + turtle.right(90) + turtle.pendown() + turtle.pencolor(col2e050b95) + turtle.forward(width, colorNo) + turtle.left(90) + turtle.penup() + col5b11d5c = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h/2.0) + turtle.left(90) + turtle.forward(width) + turtle.pendown() + turtle.pencolor(col5b11d5c) + turtle.left(90) + +# Draws letter H in colour specified by colorNo with font height h +# from the current turtle position. +def letterH(h, colorNo) : + width = h/2.0 + turtle.forward(h, colorNo) + turtle.penup() + turtle.right(90) + col2e3e48d2 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(width) + turtle.right(90) + turtle.pendown() + turtle.pencolor(col2e3e48d2) + turtle.forward(h/2.0, colorNo) + turtle.right(90) + turtle.forward(width, colorNo) + turtle.penup() + col6fb1a326 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(width) + turtle.left(90) + turtle.pendown() + turtle.pencolor(col6fb1a326) + turtle.forward(h/2.0, colorNo) + turtle.left(180) + +# Draws letter I in colour specified by colorNo with font height h +# from the current turtle position. +def letterI(h, colorNo) : + # Octagon edge length + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Cathetus of the corner triangle outside the octagon + c = b / math.sqrt(2.0) + turtle.penup() + turtle.right(90) + col3df8de97 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col3df8de97) + turtle.forward(b, colorNo) + turtle.penup() + col535a17b6 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(b/2.0) + turtle.left(90) + turtle.pendown() + turtle.pencolor(col535a17b6) + turtle.forward(h, colorNo) + turtle.penup() + turtle.right(90) + col6021ee5c = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(b/2.0) + turtle.pendown() + turtle.pencolor(col6021ee5c) + turtle.forward(b, colorNo) + turtle.penup() + col347e4e78 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(b/2 + c) + turtle.left(90) + turtle.backward(h) + turtle.pendown() + turtle.pencolor(col347e4e78) + +# Draws letter K in colour specified by colorNo with font height h +# from the current turtle position. +def letterK(h, colorNo) : + width = h/2.0 + diag = h/math.sqrt(2.0) + turtle.forward(h, colorNo) + turtle.penup() + turtle.right(90) + col13bc4968 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(width) + turtle.right(135) + turtle.pendown() + turtle.pencolor(col13bc4968) + turtle.forward(diag, colorNo) + turtle.left(90) + turtle.forward(diag, colorNo) + turtle.left(135) + +# Draws letter L in colour specified by colorNo with font height h +# from the current turtle position. +def letterL(h, colorNo) : + width = h/2.0 + turtle.forward(h, colorNo) + turtle.penup() + colc1d300f = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h) + turtle.right(90) + turtle.pendown() + turtle.pencolor(colc1d300f) + turtle.forward(width, colorNo) + turtle.left(90) + +# Draws letter M in colour specified by colorNo with font height h +# from the current turtle position. +def letterM(h, colorNo) : + width = h/2.0 + hypo = math.sqrt(width*width + h*h)/2.0 + rotAngle = math.degrees(math.atan(width/h)) + turtle.forward(h, colorNo) + turtle.left(rotAngle) + turtle.forward(-hypo, colorNo) + turtle.right(2*rotAngle) + turtle.forward(hypo, colorNo) + turtle.left(rotAngle) + turtle.forward(-h, colorNo) + +# Draws letter N in colour specified by colorNo with font height h +# from the current turtle position. +def letterN(h, colorNo) : + width = h/2.0 + hypo = math.sqrt(width*width + h*h) + rotAngle = math.degrees(math.atan(width/h)) + turtle.forward(h, colorNo) + turtle.left(rotAngle) + turtle.forward(-hypo, colorNo) + turtle.right(rotAngle) + turtle.forward(h, colorNo) + turtle.penup() + col7d3e0252 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h) + turtle.pendown() + turtle.pencolor(col7d3e0252) + +# Draws letter T in colour specified by colorNo with font height h +# from the current turtle position. +def letterT(h, colorNo) : + width = h/2.0 + turtle.penup() + col2129a0ab = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h) + turtle.pendown() + turtle.pencolor(col2129a0ab) + turtle.right(90) + turtle.forward(width, colorNo) + turtle.penup() + col5e5cb995 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(width/2.0) + turtle.pendown() + turtle.pencolor(col5e5cb995) + turtle.right(90) + turtle.forward(h, colorNo) + turtle.left(90) + turtle.penup() + col775738cb = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(width/2.0) + turtle.pendown() + turtle.pencolor(col775738cb) + turtle.left(90) + +# Draws letter V in colour specified by colorNo with font height h +# from the current turtle position. +def letterV(h, colorNo) : + width = h/2.0 + hypo = math.sqrt(h*h + width*width/4.0) + rotAngle = math.degrees(math.atan(width/2.0/h)) + turtle.penup() + col21dd9235 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h) + turtle.left(rotAngle) + turtle.pendown() + turtle.pencolor(col21dd9235) + turtle.forward(-hypo, colorNo) + turtle.right(2*rotAngle) + turtle.forward(hypo, colorNo) + turtle.penup() + turtle.left(rotAngle) + col2444e5f4 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h) + turtle.pendown() + turtle.pencolor(col2444e5f4) + +# Draws letter W in colour specified by colorNo with font height h +# from the current turtle position. +def letterW(h, colorNo) : + width = h/2.0 + width_3 = width/3.0 + hypo = math.sqrt(width_3*width_3 + h*h) + rotAngle = math.degrees(math.atan(width_3/h)) + turtle.penup() + col31a95a34 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h) + turtle.left(rotAngle) + turtle.pendown() + turtle.pencolor(col31a95a34) + turtle.forward(-hypo, colorNo) + turtle.right(2*rotAngle) + turtle.forward(hypo, colorNo) + turtle.penup() + turtle.left(90+rotAngle) + col858de1b = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(width_3) + turtle.right(90-rotAngle) + turtle.pendown() + turtle.pencolor(col858de1b) + turtle.forward(-hypo, colorNo) + turtle.right(2*rotAngle) + turtle.forward(hypo, colorNo) + turtle.penup() + turtle.left(rotAngle) + col29839e3 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h) + turtle.pendown() + turtle.pencolor(col29839e3) + +# Draws letter X in colour specified by colorNo with font height h +# from the current turtle position. +def letterX(h, colorNo) : + width = h/2.0 + hypo = math.sqrt(width*width + h*h) + rotAngle = math.degrees(math.atan(width/h)) + turtle.right(rotAngle) + turtle.forward(hypo, colorNo) + turtle.penup() + turtle.left(90+rotAngle) + col62a4f3af = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(width) + turtle.right(90-rotAngle) + turtle.pendown() + turtle.pencolor(col62a4f3af) + turtle.forward(-hypo, colorNo) + turtle.right(rotAngle) + +# Draws letter Y in colour specified by colorNo with font height h +# from the current turtle position. +def letterY(h, colorNo) : + width = h/2.0 + hypo = math.sqrt(width*width + h*h)/2.0 + rotAngle = math.degrees(math.atan(width/h)) + turtle.penup() + col6305dad8 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h) + turtle.left(rotAngle) + turtle.pendown() + turtle.pencolor(col6305dad8) + turtle.forward(-hypo, colorNo) + turtle.right(rotAngle) + turtle.penup() + cole457707 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h/2.0) + turtle.pendown() + turtle.pencolor(cole457707) + turtle.forward(h/2.0, colorNo) + turtle.right(rotAngle) + turtle.forward(hypo, colorNo) + turtle.left(rotAngle) + turtle.penup() + col3741e258 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h) + turtle.pendown() + turtle.pencolor(col3741e258) + +# Draws letter Z in colour specified by colorNo with font height h +# from the current turtle position. +def letterZ(h, colorNo) : + width = h/2.0 + hypo = math.sqrt(width*width + h*h) + rotAngle = math.degrees(math.atan(width/h)) + turtle.penup() + col2526f3be = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h) + turtle.right(90) + turtle.pendown() + turtle.pencolor(col2526f3be) + turtle.forward(width, colorNo) + turtle.left(90-rotAngle) + turtle.forward(-hypo, colorNo) + turtle.right(90-rotAngle) + turtle.forward(width, colorNo) + turtle.left(90) + +# Draws nEdges edges of a regular n-polygon with edge length a +# counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +def polygonPart(a, n, ctrclkws, nEdges, color) : + rotAngle = 360.0/n + if (ctrclkws): + rotAngle = -rotAngle + + for k in range(1, nEdges+1, 1): + turtle.right(rotAngle) + turtle.forward(a, color) + + +# Draws a dummy character (small centered square) with font height h and +# the colour encoded by colorNo +def charDummy(h, colorNo) : + width = h / 2.0 + # Octagon edge length (here: edge lengzh of the square) + b = width / (math.sqrt(2.0) + 1) + # Cathetus of the corner triangle outside the octagon + c = (width - b) / 2.0 + d = b / math.sqrt(2.0) + turtle.penup() + col350763fd = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h/2.0-b/2.0) + turtle.right(90) + turtle.forward(c) + turtle.right(90) + turtle.pendown() + turtle.pencolor(col350763fd) + # Draws the square with edge length b + polygonPart(b, 4, true, 4, colorNo) + turtle.penup() + turtle.left(90) + col6b775b97 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(b + c) + turtle.left(90) + turtle.backward(h/2.0-b/2.0) + turtle.pendown() + turtle.pencolor(col6b775b97) + +# Draws a comma in colour specified by colorNo with font height h +# from the current turtle position. +def comma(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + rotAngle = math.degrees(math.atan(0.5)) + hypo = c * math.sqrt(1.25) + turtle.penup() + turtle.right(90) + col4e0a2633 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward((c+b)/2.0 + c) + turtle.pendown() + turtle.pencolor(col4e0a2633) + # Counterclockwise draw 3 edges of a square with edge length c + # in the colour endcoded by colorNo + polygonPart(c, 4, true, 3, colorNo) + turtle.left(90) + turtle.forward(c/2.0, colorNo) + turtle.right(90) + turtle.forward(c, colorNo) + turtle.left(180 - rotAngle) + turtle.forward(hypo, colorNo) + turtle.penup() + turtle.right(90 - rotAngle) + col2a3b1dc5 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward((c + b)/2.0) + turtle.left(90) + turtle.pendown() + turtle.pencolor(col2a3b1dc5) + +# Draws an exclamation mark in the colour encoded by colorNo with font height h +# from the current turtle position. +def exclMk(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + width = h/2.0 + length1 = h - (b+c)/2.0 + length2 = length1 - 2*c + hypo = math.sqrt(width*width/16.0 + length2*length2) + # 360°/8 + rotAngle = 45 + rotAngle2 = math.degrees(math.atan(width/4.0/length2)) + turtle.penup() + col4cb21277 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(length1) + turtle.right(90) + turtle.forward(width/2.0) + turtle.left(90 + rotAngle) + turtle.pendown() + turtle.pencolor(col4cb21277) + # Clockwise draw 5 edges of an octagon with edge length b/2 + # in the colour endcoded by colorNo + polygonPart(b/2.0, 8, false, 5, colorNo) + turtle.right(rotAngle2) + turtle.forward(hypo, colorNo) + turtle.left(2*rotAngle2) + turtle.forward(-hypo, colorNo) + turtle.penup() + col76ade45a = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(hypo) + turtle.right(rotAngle2) + turtle.forward(c) + turtle.left(90) + turtle.forward(c/2.0) + turtle.pendown() + turtle.pencolor(col76ade45a) + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo) + turtle.penup() + col46748853 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward((c + b)/2.0) + turtle.left(90) + turtle.backward(c) + turtle.pendown() + turtle.pencolor(col46748853) + +# Draws a full stop in colour specified by colorNo with font height h +# from the current turtle position. +def fullSt(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + turtle.penup() + turtle.right(90) + col53a8e20e = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward((c+b)/2.0 + c) + turtle.pendown() + turtle.pencolor(col53a8e20e) + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart(c, 4, true, 4, colorNo) + turtle.penup() + col7282f25a = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward((c + b)/2.0) + turtle.left(90) + turtle.pendown() + turtle.pencolor(col7282f25a) + +# Draws letter B in colour specified by colorNo with font height h +# from the current turtle position. +def letterB(h, colorNo) : + # Octagon edge length + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Cathetus of the outer corner triangle of the octagon + c = b / math.sqrt(2.0) + turtle.forward(h, colorNo) + turtle.right(90) + turtle.forward(c+b, colorNo) + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo) + turtle.forward(c, colorNo) + turtle.penup() + turtle.left(180) + col23a37a61 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(b + c) + turtle.pendown() + turtle.pencolor(col23a37a61) + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart(b, 8, false, 4, colorNo) + turtle.forward(c, colorNo) + turtle.penup() + turtle.left(180) + col49d95dd1 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(b + 2*c) + turtle.pendown() + turtle.pencolor(col49d95dd1) + turtle.left(90) + +# Draws letter C in the colour encoded by colorNo with font height h +# from the current turtle position. +def letterC(h, colorNo) : + # Octagon edge length + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Cathetus of the outer trinagle at the octagon corner + c = b / math.sqrt(2.0) + # 360°/8 + rotAngle = 45 + turtle.penup() + col3d6ded67 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col3d6ded67) + turtle.right(180) + # Clockwise draws 3 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart(b, 8, true, 3, colorNo) + turtle.left(rotAngle) + turtle.penup() + col5f0be849 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(2*b + 2*c) + turtle.pendown() + turtle.pencolor(col5f0be849) + # Counterclockwise draws 4 edges of an octagon with edge length b + # iin the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo) + turtle.forward(b + 2*c, colorNo) + turtle.penup() + col2f89a87f = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.left(90) + turtle.pencolor(col2f89a87f) + turtle.forward(b + 2*c, colorNo) + turtle.pendown() + turtle.left(90) + +# Draws letter D in colour specified by colorNo with font height h +# from the current turtle position. +def letterD(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + turtle.forward(h, colorNo) + turtle.right(90) + turtle.forward(c+b, colorNo) + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart(b, 8, false, 2, colorNo) + turtle.forward(b + 2*c, colorNo) + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart(b, 8, false, 2, colorNo) + turtle.forward(c, colorNo) + turtle.penup() + turtle.left(180) + col5e226745 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(b + 2*c) + turtle.pendown() + turtle.pencolor(col5e226745) + turtle.left(90) + +# Draws letter G in colour specified by colorNo with font height h +# from the current turtle position. +def letterG(h, colorNo) : + # Octagon edge length + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Cathetus of the corner triangle outside the octagon. + c = b / math.sqrt(2.0) + turtle.penup() + col2689194e = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col2689194e) + turtle.right(180) + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo) + turtle.forward(c, colorNo) + turtle.left(90) + turtle.forward(b/2.0 + c, colorNo) + turtle.penup() + col5e1d35a = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(b/2.0 + c) + turtle.right(90) + turtle.forward(b + c) + turtle.pendown() + turtle.pencolor(col5e1d35a) + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart(b, 8, true, 4, colorNo) + turtle.forward(b + 2*c, colorNo) + turtle.penup() + col7ffa9517 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.left(90) + turtle.pencolor(col7ffa9517) + turtle.forward(b + 2*c, colorNo) + turtle.pendown() + turtle.left(90) + +# Draws letter J in colour encoded by colorNo with font height h +# from the current turtle position. +def letterJ(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + # 360°/8 + rotAngle = 45 + turtle.penup() + col542787d2 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col542787d2) + turtle.right(180) + # Counterclockwise draw 3 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart(b, 8, true, 3, colorNo) + turtle.left(rotAngle) + turtle.forward(h - c, colorNo) + turtle.penup() + col7d490d25 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h) + turtle.pendown() + turtle.pencolor(col7d490d25) + +# Draws letter O in colour specified by colorNo with font height h +# from the current turtle position. +def letterO(h, colorNo) : + # Octagon edge length + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Cathetus of the corner triangle outside the octagon + c = b / math.sqrt(2.0) + turtle.penup() + col57c549e7 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col57c549e7) + turtle.right(180) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo) + turtle.forward(b + 2*c, colorNo) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo) + turtle.forward(b + 2*c, colorNo) + turtle.penup() + col50c8a80c = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.left(90) + turtle.forward(b + 2*c) + turtle.pendown() + turtle.pencolor(col50c8a80c) + turtle.left(90) + +# Draws letter P in colour specified by colorNo with font height h +# from the current turtle position. +def letterP(h, colorNo) : + # Octagon edge length + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Cathetus of the corner triangle outside the octagon + c = b / math.sqrt(2.0) + turtle.forward(h, colorNo) + turtle.right(90) + turtle.forward(c+b, colorNo) + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo) + turtle.forward(c, colorNo) + turtle.penup() + col7267b53d = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(b + 2*c) + turtle.left(90) + turtle.forward(b + 2*c) + turtle.pendown() + turtle.pencolor(col7267b53d) + turtle.left(180) + +# Draws letter Q in colour specified by colorNo with font height h +# from the current turtle position. +def letterQ(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + # 360°/8 + rotAngle = 45 + turtle.penup() + col3b0d1bfb = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col3b0d1bfb) + turtle.right(180) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo) + turtle.forward(b + 2*c, colorNo) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, true, 4, colorNo) + turtle.forward(b + 2*c, colorNo) + turtle.penup() + col568cf7dc = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.left(90) + turtle.forward(b + 2*c) + turtle.pencolor(col568cf7dc) + turtle.right(rotAngle) + col6d0648de = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(b) + turtle.pendown() + turtle.pencolor(col6d0648de) + turtle.forward(b, colorNo) + turtle.left(90 + rotAngle) + +# Zeichnet den Buchstaben R von der Turtleposition aus +# mit Zeilenhöhe h +def letterR(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + # 360°/8 + rotAngle = 45 + turtle.forward(h, colorNo) + turtle.right(90) + turtle.forward(c+b, colorNo) + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, false, 4, colorNo) + turtle.forward(c, colorNo) + turtle.left(90 + rotAngle) + turtle.forward(math.sqrt(2.0)*(b + 2*c), colorNo) + turtle.left(90 + rotAngle) + +# Draws letter S in colour specified by colorNo with font height h +# from the current turtle position. +def letterS(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + # 360°/8 + rotAngle = 45 + turtle.penup() + col1e851227 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col1e851227) + turtle.right(180) + # Counterclockwise draw 6 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, true, 6, colorNo) + # Clockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo) + turtle.right(rotAngle) + turtle.penup() + col72fd2ff3 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(2*b + 3*c) + turtle.pendown() + turtle.pencolor(col72fd2ff3) + turtle.left(180) + +# Draws letter U in colour specified by colorNo with font height h +# from the current turtle position. +def letterU(h, colorNo) : + # edge length of a regular octagon + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + # 360°/8 + rotAngle = 45 + turtle.penup() + col14e62435 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.pendown() + turtle.pencolor(col14e62435) + turtle.forward(h - c, colorNo) + turtle.penup() + col28bff43f = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h-c) + turtle.pendown() + turtle.pencolor(col28bff43f) + turtle.right(180) + # Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart(b, 8, true, 3, colorNo) + turtle.left(rotAngle) + turtle.forward(h - c, colorNo) + turtle.penup() + col7283c779 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.backward(h) + turtle.pendown() + turtle.pencolor(col7283c779) + +# Draws a question mark in colour specified by colorNo with font height h +# from the current turtle position. +def qstnMk(h, colorNo) : + # Achteck-Kantenlänge + b = h * 0.5 / (math.sqrt(2.0) + 1) + # Eckenlänge außen am Achteck + c = b / math.sqrt(2.0) + # 360°/8 + rotAngle = 45 + turtle.penup() + col67b7a80 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(h-c) + turtle.pendown() + turtle.pencolor(col67b7a80) + # Counterclockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart(b, 8, false, 5, colorNo) + turtle.forward(c, colorNo) + turtle.left(rotAngle) + turtle.forward(b/2.0, colorNo) + turtle.penup() + col382cadbb = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(c) + turtle.left(90) + turtle.forward(c/2.0) + turtle.pendown() + turtle.pencolor(col382cadbb) + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart(c, 4, false, 4, colorNo) + turtle.penup() + col2ca0b807 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward((c + b)/2.0) + turtle.left(90) + turtle.backward(c) + turtle.pendown() + turtle.pencolor(col2ca0b807) + +# Has the turtle draw the given string 'text´ with font height 'h´ (in +# pixels) and the colour coded by integer 'c´ from the current Turtle +# position to the Turtle canvas. If the turtle looks North then +# the text will be written rightwards. In the event, the turtle will be +# placed behind the text in original orientation (such that the next text +# would be written like a continuation. Colour codes: +# 1 = black +# 2 = red +# 3 = yellow +# 4 = green +# 5 = cyan +# 6 = blue +# 7 = pink +# 8 = grey +# 9 = orange +# 10 = violet +# All letters (ASCII) will be converted to uppercase, digits cannot +# be represented, the set of representable special characters is: +# '.', ',', '!', '?'. Other characters will be shown as a small +# centred square (dummy character). +def drawText(text, h, c) : + gap = h/10.0 + for k in range(1, length(text)+1, 1): + letter = uppercase(copy(text, k, 1)) + if (letter == ","): + comma(h,c) + else: + # "," cannot be chacked against because the comma is misinterpreted + # as selector list separator. + if ((letter) == "A") : + letterA(h,c) + elif ((letter) == "B") : + letterB(h,c) + elif ((letter) == "C") : + letterC(h,c) + elif ((letter) == "D") : + letterD(h,c) + elif ((letter) == "E") : + letterE(h,c) + elif ((letter) == "F") : + letterF(h,c) + elif ((letter) == "G") : + letterG(h,c) + elif ((letter) == "H") : + letterH(h,c) + elif ((letter) == "I") : + letterI(h,c) + elif ((letter) == "J") : + letterJ(h,c) + elif ((letter) == "K") : + letterK(h,c) + elif ((letter) == "L") : + letterL(h,c) + elif ((letter) == "M") : + letterM(h,c) + elif ((letter) == "N") : + letterN(h,c) + elif ((letter) == "O") : + letterO(h,c) + elif ((letter) == "P") : + letterP(h,c) + elif ((letter) == "Q") : + letterQ(h,c) + elif ((letter) == "R") : + letterR(h,c) + elif ((letter) == "S") : + letterS(h,c) + elif ((letter) == "T") : + letterT(h,c) + elif ((letter) == "U") : + letterU(h,c) + elif ((letter) == "V") : + letterV(h,c) + elif ((letter) == "W") : + letterW(h,c) + elif ((letter) == "X") : + letterX(h,c) + elif ((letter) == "Y") : + letterY(h,c) + elif ((letter) == "Z") : + letterZ(h,c) + elif ((letter) == " ") : + blank(h,c) + elif ((letter) == "!") : + exclMk(h,c) + elif ((letter) == "?") : + qstnMk(h,c) + elif ((letter) == ".") : + fullSt(h,c) + else: + charDummy(h,c) + + turtle.right(90) + turtle.penup() + col320ac4f1 = turtle.pencolor(); turtle.pencolor("#000000") + turtle.forward(gap) + turtle.pendown() + turtle.left(90) + turtle.pencolor(col320ac4f1) + + +# Demo program for routine drawText() +# Asks the user to enter a text, a wanted text height and colour, +# and then draws this string onto the turtle screen. Places every +# entered text to a new line. +print("This is a demo program for text writing with Turleizer.", sep='') +turtle.showturtle() +turtle.pendown() +y = 0 +while True: + text = input("Enter some text (empty string to exit)") + # Make sure the content is interpreted as string + text = "" + text + if (text != ""): + while True: + height = input("Height of the text (pixels)") + if height >= 5: + break + + while True: + colour = input("Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)") + if colour >= 1 and colour <= 10: + break + + y = y + height + 2 + turtle.goto(0, y - 2) + drawText(text, height, colour) + + if text == "": + break + +turtle.goto(0, y + 15) +drawText("Thank you, bye.", 10, 4) +turtle.hideturtle() +# turtle.bye() # TODO: re-enable this if you want to close the turtle window. diff --git a/samples/export/StrukTeX/ELIZA_2.3.tex b/samples/export/StrukTeX/ELIZA_2.3.tex new file mode 100644 index 00000000..a73dbbf6 --- /dev/null +++ b/samples/export/StrukTeX/ELIZA_2.3.tex @@ -0,0 +1,414 @@ +\documentclass[a4paper,10pt]{article} + +\usepackage{struktex} +\usepackage{german} +\usepackage{mathcomp} + +\title{Structorizer StrukTeX Export of ELIZA\_2.3.arrz} +\author{Kay Gürtzig} +\date{29.11.2019} + +\begin{document} + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(171,114)[adjustSpelling] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{sentence}}{type: \(string\)} + \end{declaration} + \begin{declaration}[Result type:] + \description{string}{} + \end{declaration} + } + \assign{\(result\ \gets\ sentence\)} + \assign{\(position\ \gets\ 1\)} + \while{\((position\ \leq\ length(sentence))\ \wedge\ (copy(sentence,\ position,\ 1)\ =\ \)"{}\ "{}\()\)} + \assign{\(position\ \gets\ position\ +\ 1\)} + \whileend + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{10}{2}... + \ifthenelse{10}{2}{\(position\ \leq\ length(sentence)\)}{ja}{nein} + \assign{\(start\ \gets\ copy(sentence,\ 1,\ position)\)} + \assign{\(delete(result,\ 1,\ position)\)} + \assign{\(insert(uppercase(start),\ result,\ 1)\)} + \change + \ifend + \while{\(\forall word\in \{\)"{}\ i\ "{}\(,\ \)"{}\ i\'{}"{}\(\}\)} + \assign{\(position\ \gets\ pos(word,\ result)\)} + \while{\(position\ >\ 0\)} + \assign{\(delete(result,\ position+1,\ 1)\)} + \assign{\(insert(\)"{}I"{}\(,\ result,\ position+1)\)} + \assign{\(position\ \gets\ pos(word,\ result)\)} + \whileend + \whileend +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(183,68)[checkGoodBye] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{text}}{type: \(string\)} + \description{\pVar{phrases}}{type: \(array\ of\ array[0..1]\ of\ string\)} + \end{declaration} + \begin{declaration}[Result type:] + \description{boolean}{} + \end{declaration} + } + \while{\(\forall pair\in phrases\)} + \ifthenelse{5}{1}{\(pos(pair[0],\ text)\ >\ 0\)}{ja}{nein} + \assign{\(saidBye\ \gets\ true\)} + \assign{\(\)\pKey{OUTPUT}\(\ pair[1]\)} + \exit{\(\)\pKey{return}\(\ true\)} + \change + \ifend + \whileend + \assign{\(\)\pKey{return}\(\ false\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(169,95)[checkRepetition] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{history}}{type: \(History\)} + \description{\pVar{newInput}}{type: \(string\)} + \end{declaration} + \begin{declaration}[Result type:] + \description{boolean}{} + \end{declaration} + \begin{declaration}[Requires:] + \description{History}{} + \end{declaration} + } + \assign{\(hasOccurred\ \gets\ false\)} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{10}{2}... + \ifthenelse{10}{2}{\(length(newInput)\ >\ 4\)}{ja}{nein} + \assign{\(histDepth\ \gets\ length(history.histArray)\)} + \while{\pKey{for}\(i\ \gets\ 0\)\pKey{to}\(histDepth-1\)} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{3}{1}... + \ifthenelse{3}{1}{\(newInput\ =\ history.histArray[i]\)}{ja}{nein} + \assign{\(hasOccurred\ \gets\ true\)} + \change + \ifend + \whileend + \assign{\(history.histArray[history.histIndex]\ \gets\ newInput\)} + \assign{\(history.histIndex\ \gets\ (history.histIndex\ +\ 1)\ \)\pKey{mod}\(\ (histDepth)\)} + \change + \ifend + \assign{\(\)\pKey{return}\(\ hasOccurred\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(265,102)[conjugateStrings] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{sentence}}{type: \(string\)} + \description{\pVar{key}}{type: \(string\)} + \description{\pVar{keyPos}}{type: \(integer\)} + \description{\pVar{flexions}}{type: \(array\ of\ array[0..1]\ of\ string\)} + \end{declaration} + \begin{declaration}[Result type:] + \description{string}{} + \end{declaration} + } + \assign{\(result\ \gets\ \)"{}\ "{}\(\ +\ copy(sentence,\ keyPos\ +\ length(key),\ length(sentence))\ +\ \)"{}\ "{}\(\)} + \while{\(\forall pair\in flexions\)} + \assign{\(left\ \gets\ \)"{}"{}\(\)} + \assign{\(right\ \gets\ result\)} + \assign{\(position\ \gets\ pos(pair[0],\ right)\)} + \while{\(position\ >\ 0\)} + \assign{\(left\ \gets\ left\ +\ copy(right,\ 1,\ position-1)\ +\ pair[1]\)} + \assign{\(right\ \gets\ copy(right,\ position\ +\ length(pair[0]),\ length(right))\)} + \assign{\(position\ \gets\ pos(pair[0],\ right)\)} + \whileend + \assign{\(result\ \gets\ left\ +\ right\)} + \whileend + \assign{\(position\ \gets\ pos(\)"{}\ \ "{}\(,\ result)\)} + \while{\(position\ >\ 0\)} + \assign{\(result\ \gets\ copy(result,\ 1,\ position-1)\ +\ copy(result,\ position+1,\ length(result))\)} + \assign{\(position\ \gets\ pos(\)"{}\ \ "{}\(,\ result)\)} + \whileend +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(220,99)[findKeyword] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{keyMap}}{type: \(const\ array\ of\ KeyMapEntry\)} + \description{\pVar{sentence}}{type: \(string\)} + \end{declaration} + \begin{declaration}[Result type:] + \description{array[0..1] of integer}{} + \end{declaration} + \begin{declaration}[Requires:] + \description{KeyMapEntry}{} + \end{declaration} + } + \assign{\(result\ \gets\ \{-1,\ 0\}\)} + \assign{\(i\ \gets\ 0\)} + \while{\((result[0]\ <\ 0)\ \wedge\ (i\ <\ length(keyMap))\)} + \assign{\(var\ entry:\ KeyMapEntry\ \gets\ keyMap[i]\)} + \assign{\(position\ \gets\ pos(entry.keyword,\ sentence)\)} + \ifthenelse{5}{1}{\(position\ >\ 0\)}{ja}{nein} + \assign{\(result[0]\ \gets\ i\)} + \assign{\(result[1]\ \gets\ position\)} + \change + \ifend + \assign{\(i\ \gets\ i+1\)} + \whileend +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(238,69)[normalizeInput] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{sentence}}{type: \(string\)} + \end{declaration} + \begin{declaration}[Result type:] + \description{string}{} + \end{declaration} + } + \assign{\(sentence\ \gets\ lowercase(sentence)\)} + \while{\(\forall symbol\in \{\)'{}.'{}\(,\ \)'{},'{}\(,\ \)'{};'{}\(,\ \)'{}!'{}\(,\ \)'{}?'{}\(\}\)} + \assign{\(position\ \gets\ pos(symbol,\ sentence)\)} + \while{\(position\ >\ 0\)} + \assign{\(sentence\ \gets\ copy(sentence,\ 1,\ position-1)\ +\ copy(sentence,\ position+1,\ length(sentence))\)} + \assign{\(position\ \gets\ pos(symbol,\ sentence)\)} + \whileend + \whileend + \assign{\(result\ \gets\ \)"{}\ "{}\(\ +\ sentence\ +\ \)"{}\ "{}\(\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(186,31)[setupGoodByePhrases] + \assign{% + \begin{declaration}[Result type:] + \description{array of array[0..1] of string}{} + \end{declaration} + } + \assign{\(phrases[0]\ \gets\ \{\)"{}\ shut"{}\(,\ \)"{}Okay.\ If\ you\ feel\ that\ way\ I\'{}ll\ shut\ up.\ ...\ Your\ choice."{}\(\}\)} + \assign{\(phrases[1]\ \gets\ \{\)"{}bye"{}\(,\ \)"{}Well,\ let\'{}s\ end\ our\ talk\ for\ now.\ See\ you\ later.\ Bye."{}\(\}\)} + \assign{\(\)\pKey{return}\(\ phrases\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(125,150)[setupKeywords] + \assign{% + \begin{declaration}[Result type:] + \description{array of KeyMapEntry}{} + \end{declaration} + \begin{declaration}[Requires:] + \description{KeyMapEntry}{} + \end{declaration} + } + \assign{\(keywords[39]\ \gets\ KeyMapEntry\{\)"{}"{}\(,\ 29\}\)} + \assign{\(keywords[0]\ \gets\ KeyMapEntry\{\)"{}can\ you\ "{}\(,\ 0\}\)} + \assign{\(keywords[1]\ \gets\ KeyMapEntry\{\)"{}can\ i\ "{}\(,\ 1\}\)} + \assign{\(keywords[2]\ \gets\ KeyMapEntry\{\)"{}you\ are\ "{}\(,\ 2\}\)} + \assign{\(keywords[3]\ \gets\ KeyMapEntry\{\)"{}you\'{}re\ "{}\(,\ 2\}\)} + \assign{\(keywords[4]\ \gets\ KeyMapEntry\{\)"{}i\ don'{}t\ "{}\(,\ 3\}\)} + \assign{\(keywords[5]\ \gets\ KeyMapEntry\{\)"{}i\ feel\ "{}\(,\ 4\}\)} + \assign{\(keywords[6]\ \gets\ KeyMapEntry\{\)"{}why\ don\'{}t\ you\ "{}\(,\ 5\}\)} + \assign{\(keywords[7]\ \gets\ KeyMapEntry\{\)"{}why\ can\'{}t\ i\ "{}\(,\ 6\}\)} + \assign{\(keywords[8]\ \gets\ KeyMapEntry\{\)"{}are\ you\ "{}\(,\ 7\}\)} + \assign{\(keywords[9]\ \gets\ KeyMapEntry\{\)"{}i\ can\'{}t\ "{}\(,\ 8\}\)} + \assign{\(keywords[10]\ \gets\ KeyMapEntry\{\)"{}i\ am\ "{}\(,\ 9\}\)} + \assign{\(keywords[11]\ \gets\ KeyMapEntry\{\)"{}i\'{}m\ "{}\(,\ 9\}\)} + \assign{\(keywords[12]\ \gets\ KeyMapEntry\{\)"{}you\ "{}\(,\ 10\}\)} + \assign{\(keywords[13]\ \gets\ KeyMapEntry\{\)"{}i\ want\ "{}\(,\ 11\}\)} + \assign{\(keywords[14]\ \gets\ KeyMapEntry\{\)"{}what\ "{}\(,\ 12\}\)} + \assign{\(keywords[15]\ \gets\ KeyMapEntry\{\)"{}how\ "{}\(,\ 12\}\)} + \assign{\(keywords[16]\ \gets\ KeyMapEntry\{\)"{}who\ "{}\(,\ 12\}\)} + \assign{\(keywords[17]\ \gets\ KeyMapEntry\{\)"{}where\ "{}\(,\ 12\}\)} + \assign{\(keywords[18]\ \gets\ KeyMapEntry\{\)"{}when\ "{}\(,\ 12\}\)} + \assign{\(keywords[19]\ \gets\ KeyMapEntry\{\)"{}why\ "{}\(,\ 12\}\)} + \assign{\(keywords[20]\ \gets\ KeyMapEntry\{\)"{}name\ "{}\(,\ 13\}\)} + \assign{\(keywords[21]\ \gets\ KeyMapEntry\{\)"{}cause\ "{}\(,\ 14\}\)} + \assign{\(keywords[22]\ \gets\ KeyMapEntry\{\)"{}sorry\ "{}\(,\ 15\}\)} + \assign{\(keywords[23]\ \gets\ KeyMapEntry\{\)"{}dream\ "{}\(,\ 16\}\)} + \assign{\(keywords[24]\ \gets\ KeyMapEntry\{\)"{}hello\ "{}\(,\ 17\}\)} + \assign{\(keywords[25]\ \gets\ KeyMapEntry\{\)"{}hi\ "{}\(,\ 17\}\)} + \assign{\(keywords[26]\ \gets\ KeyMapEntry\{\)"{}maybe\ "{}\(,\ 18\}\)} + \assign{\(keywords[27]\ \gets\ KeyMapEntry\{\)"{}\ no"{}\(,\ 19\}\)} + \assign{\(keywords[28]\ \gets\ KeyMapEntry\{\)"{}your\ "{}\(,\ 20\}\)} + \assign{\(keywords[29]\ \gets\ KeyMapEntry\{\)"{}always\ "{}\(,\ 21\}\)} + \assign{\(keywords[30]\ \gets\ KeyMapEntry\{\)"{}think\ "{}\(,\ 22\}\)} + \assign{\(keywords[31]\ \gets\ KeyMapEntry\{\)"{}alike\ "{}\(,\ 23\}\)} + \assign{\(keywords[32]\ \gets\ KeyMapEntry\{\)"{}yes\ "{}\(,\ 24\}\)} + \assign{\(keywords[33]\ \gets\ KeyMapEntry\{\)"{}friend\ "{}\(,\ 25\}\)} + \assign{\(keywords[34]\ \gets\ KeyMapEntry\{\)"{}computer"{}\(,\ 26\}\)} + \assign{\(keywords[35]\ \gets\ KeyMapEntry\{\)"{}bot\ "{}\(,\ 26\}\)} + \assign{\(keywords[36]\ \gets\ KeyMapEntry\{\)"{}smartphone"{}\(,\ 27\}\)} + \assign{\(keywords[37]\ \gets\ KeyMapEntry\{\)"{}father\ "{}\(,\ 28\}\)} + \assign{\(keywords[38]\ \gets\ KeyMapEntry\{\)"{}mother\ "{}\(,\ 28\}\)} + \assign{\(\)\pKey{return}\(\ keywords\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(114,90)[setupReflexions] + \assign{% + \begin{declaration}[Result type:] + \description{array of array[0..1] of string}{} + \end{declaration} + } + \assign{\(reflexions[0]\ \gets\ \{\)"{}\ are\ "{}\(,\ \)"{}\ am\ "{}\(\}\)} + \assign{\(reflexions[1]\ \gets\ \{\)"{}\ were\ "{}\(,\ \)"{}\ was\ "{}\(\}\)} + \assign{\(reflexions[2]\ \gets\ \{\)"{}\ you\ "{}\(,\ \)"{}\ I\ "{}\(\}\)} + \assign{\(reflexions[3]\ \gets\ \{\)"{}\ your"{}\(,\ \)"{}\ my"{}\(\}\)} + \assign{\(reflexions[4]\ \gets\ \{\)"{}\ i\'{}ve\ "{}\(,\ \)"{}\ you\'{}ve\ "{}\(\}\)} + \assign{\(reflexions[5]\ \gets\ \{\)"{}\ i\'{}m\ "{}\(,\ \)"{}\ you\'{}re\ "{}\(\}\)} + \assign{\(reflexions[6]\ \gets\ \{\)"{}\ me\ "{}\(,\ \)"{}\ you\ "{}\(\}\)} + \assign{\(reflexions[7]\ \gets\ \{\)"{}\ my\ "{}\(,\ \)"{}\ your\ "{}\(\}\)} + \assign{\(reflexions[8]\ \gets\ \{\)"{}\ i\ "{}\(,\ \)"{}\ you\ "{}\(\}\)} + \assign{\(reflexions[9]\ \gets\ \{\)"{}\ am\ "{}\(,\ \)"{}\ are\ "{}\(\}\)} + \assign{\(\)\pKey{return}\(\ reflexions\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(154,549)[setupReplies] + \assign{% + \begin{declaration}[Result type:] + \description{array of array of string}{} + \end{declaration} + } + \assign{% + \begin{declaration}[variable:] + \description{replies}{var\ replies:\ array\ of\ array\ of\ String} + \end{declaration} + } + \assign{\(replies[29]\ \gets\ \{\ \)"{}Say,\ do\ you\ have\ any\ psychological\ problems?"{}\(,\ \)"{}What\ does\ that\ suggest\ to\ you?"{}\(,\ \)"{}I\ see."{}\(,\ \)"{}I'{}m\ not\ sure\ I\ understand\ you\ fully."{}\(,\ \)"{}Come\ come\ elucidate\ your\ thoughts."{}\(,\ \)"{}Can\ you\ elaborate\ on\ that?"{}\(,\ \)"{}That\ is\ quite\ interesting."{}\(\}\)} + \assign{\(replies[0]\ \gets\ \{\ \)"{}Don'{}t\ you\ believe\ that\ I\ can*?"{}\(,\ \)"{}Perhaps\ you\ would\ like\ to\ be\ like\ me?"{}\(,\ \)"{}You\ want\ me\ to\ be\ able\ to*?"{}\(\}\)} + \assign{\(replies[1]\ \gets\ \{\ \)"{}Perhaps\ you\ don'{}t\ want\ to*?"{}\(,\ \)"{}Do\ you\ want\ to\ be\ able\ to*?"{}\(\}\)} + \assign{\(replies[2]\ \gets\ \{\ \)"{}What\ makes\ you\ think\ I\ am*?"{}\(,\ \)"{}Does\ it\ please\ you\ to\ believe\ I\ am*?"{}\(,\ \)"{}Perhaps\ you\ would\ like\ to\ be*?"{}\(,\ \)"{}Do\ you\ sometimes\ wish\ you\ were*?"{}\(\}\)} + \assign{\(replies[3]\ \gets\ \{\ \)"{}Don'{}t\ you\ really*?"{}\(,\ \)"{}Why\ don'{}t\ you*?"{}\(,\ \)"{}Do\ you\ wish\ to\ be\ able\ to*?"{}\(,\ \)"{}Does\ that\ trouble\ you*?"{}\(\}\)} + \assign{\(replies[4]\ \gets\ \{\ \)"{}Do\ you\ often\ feel*?"{}\(,\ \)"{}Are\ you\ afraid\ of\ feeling*?"{}\(,\ \)"{}Do\ you\ enjoy\ feeling*?"{}\(\}\)} + \assign{\(replies[5]\ \gets\ \{\ \)"{}Do\ you\ really\ believe\ I\ don'{}t*?"{}\(,\ \)"{}Perhaps\ in\ good\ time\ I\ will*."{}\(,\ \)"{}Do\ you\ want\ me\ to*?"{}\(\}\)} + \assign{\(replies[6]\ \gets\ \{\ \)"{}Do\ you\ think\ you\ should\ be\ able\ to*?"{}\(,\ \)"{}Why\ can'{}t\ you*?"{}\(\}\)} + \assign{\(replies[7]\ \gets\ \{\ \)"{}Why\ are\ you\ interested\ in\ whether\ or\ not\ I\ am*?"{}\(,\ \)"{}Would\ you\ prefer\ if\ I\ were\ not*?"{}\(,\ \)"{}Perhaps\ in\ your\ fantasies\ I\ am*?"{}\(\}\)} + \assign{\(replies[8]\ \gets\ \{\ \)"{}How\ do\ you\ know\ you\ can'{}t*?"{}\(,\ \)"{}Have\ you\ tried?"{}\(,\)"{}Perhaps\ you\ can\ now*."{}\(\}\)} + \assign{\(replies[9]\ \gets\ \{\ \)"{}Did\ you\ come\ to\ me\ because\ you\ are*?"{}\(,\ \)"{}How\ long\ have\ you\ been*?"{}\(,\ \)"{}Do\ you\ believe\ it\ is\ normal\ to\ be*?"{}\(,\ \)"{}Do\ you\ enjoy\ being*?"{}\(\}\)} + \assign{\(replies[10]\ \gets\ \{\ \)"{}We\ were\ discussing\ you--not\ me."{}\(,\ \)"{}Oh,\ I*."{}\(,\ \)"{}You'{}re\ not\ really\ talking\ about\ me,\ are\ you?"{}\(\}\)} + \assign{\(replies[11]\ \gets\ \{\ \)"{}What\ would\ it\ mean\ to\ you\ if\ you\ got*?"{}\(,\ \)"{}Why\ do\ you\ want*?"{}\(,\ \)"{}Suppose\ you\ soon\ got*..."{}\(,\ \)"{}What\ if\ you\ never\ got*?"{}\(,\ \)"{}I\ sometimes\ also\ want*."{}\(\}\)} + \assign{\(replies[12]\ \gets\ \{\ \)"{}Why\ do\ you\ ask?"{}\(,\ \)"{}Does\ that\ question\ interest\ you?"{}\(,\ \)"{}What\ answer\ would\ please\ you\ the\ most?"{}\(,\ \)"{}What\ do\ you\ think?"{}\(,\ \)"{}Are\ such\ questions\ on\ your\ mind\ often?"{}\(,\ \)"{}What\ is\ it\ that\ you\ really\ want\ to\ know?"{}\(,\ \)"{}Have\ you\ asked\ anyone\ else?"{}\(,\ \)"{}Have\ you\ asked\ such\ questions\ before?"{}\(,\ \)"{}What\ else\ comes\ to\ mind\ when\ you\ ask\ that?"{}\(\}\)} + \assign{\(replies[13]\ \gets\ \{\ \)"{}Names\ don'{}t\ interest\ me."{}\(,\ \)"{}I\ don'{}t\ care\ about\ names\ --\ please\ go\ on."{}\(\}\)} + \assign{\(replies[14]\ \gets\ \{\ \)"{}Is\ that\ the\ real\ reason?"{}\(,\ \)"{}Don'{}t\ any\ other\ reasons\ come\ to\ mind?"{}\(,\ \)"{}Does\ that\ reason\ explain\ anything\ else?"{}\(,\ \)"{}What\ other\ reasons\ might\ there\ be?"{}\(\}\)} + \assign{\(replies[15]\ \gets\ \{\ \)"{}Please\ don'{}t\ apologize!"{}\(,\ \)"{}Apologies\ are\ not\ necessary."{}\(,\ \)"{}What\ feelings\ do\ you\ have\ when\ you\ apologize?"{}\(,\ \)"{}Don'{}t\ be\ so\ defensive!"{}\(\}\)} + \assign{\(replies[16]\ \gets\ \{\ \)"{}What\ does\ that\ dream\ suggest\ to\ you?"{}\(,\ \)"{}Do\ you\ dream\ often?"{}\(,\ \)"{}What\ persons\ appear\ in\ your\ dreams?"{}\(,\ \)"{}Are\ you\ disturbed\ by\ your\ dreams?"{}\(\}\)} + \assign{\(replies[17]\ \gets\ \{\ \)"{}How\ do\ you\ do\ ...please\ state\ your\ problem."{}\(\}\)} + \assign{\(replies[18]\ \gets\ \{\ \)"{}You\ don'{}t\ seem\ quite\ certain."{}\(,\ \)"{}Why\ the\ uncertain\ tone?"{}\(,\ \)"{}Can'{}t\ you\ be\ more\ positive?"{}\(,\ \)"{}You\ aren'{}t\ sure?"{}\(,\ \)"{}Don'{}t\ you\ know?"{}\(\}\)} + \assign{\(replies[19]\ \gets\ \{\ \)"{}Are\ you\ saying\ no\ just\ to\ be\ negative?"{}\(,\ \)"{}You\ are\ being\ a\ bit\ negative."{}\(,\ \)"{}Why\ not?"{}\(,\ \)"{}Are\ you\ sure?"{}\(,\ \)"{}Why\ no?"{}\(\}\)} + \assign{\(replies[20]\ \gets\ \{\ \)"{}Why\ are\ you\ concerned\ about\ my*?"{}\(,\ \)"{}What\ about\ your\ own*?"{}\(\}\)} + \assign{\(replies[21]\ \gets\ \{\ \)"{}Can\ you\ think\ of\ a\ specific\ example?"{}\(,\ \)"{}When?"{}\(,\ \)"{}What\ are\ you\ thinking\ of?"{}\(,\ \)"{}Really,\ always?"{}\(\}\)} + \assign{\(replies[22]\ \gets\ \{\ \)"{}Do\ you\ really\ think\ so?"{}\(,\ \)"{}But\ you\ are\ not\ sure\ you*?"{}\(,\ \)"{}Do\ you\ doubt\ you*?"{}\(\}\)} + \assign{\(replies[23]\ \gets\ \{\ \)"{}In\ what\ way?"{}\(,\ \)"{}What\ resemblance\ do\ you\ see?"{}\(,\ \)"{}What\ does\ the\ similarity\ suggest\ to\ you?"{}\(,\ \)"{}What\ other\ connections\ do\ you\ see?"{}\(,\ \)"{}Could\ there\ really\ be\ some\ connection?"{}\(,\ \)"{}How?"{}\(,\ \)"{}You\ seem\ quite\ positive."{}\(\}\)} + \assign{\(replies[24]\ \gets\ \{\ \)"{}Are\ you\ sure?"{}\(,\ \)"{}I\ see."{}\(,\ \)"{}I\ understand."{}\(\}\)} + \assign{\(replies[25]\ \gets\ \{\ \)"{}Why\ do\ you\ bring\ up\ the\ topic\ of\ friends?"{}\(,\ \)"{}Do\ your\ friends\ worry\ you?"{}\(,\ \)"{}Do\ your\ friends\ pick\ on\ you?"{}\(,\ \)"{}Are\ you\ sure\ you\ have\ any\ friends?"{}\(,\ \)"{}Do\ you\ impose\ on\ your\ friends?"{}\(,\ \)"{}Perhaps\ your\ love\ for\ friends\ worries\ you."{}\(\}\)} + \assign{\(replies[26]\ \gets\ \{\ \)"{}Do\ computers\ worry\ you?"{}\(,\ \)"{}Are\ you\ talking\ about\ me\ in\ particular?"{}\(,\ \)"{}Are\ you\ frightened\ by\ machines?"{}\(,\ \)"{}Why\ do\ you\ mention\ computers?"{}\(,\ \)"{}What\ do\ you\ think\ machines\ have\ to\ do\ with\ your\ problem?"{}\(,\ \)"{}Don'{}t\ you\ think\ computers\ can\ help\ people?"{}\(,\ \)"{}What\ is\ it\ about\ machines\ that\ worries\ you?"{}\(\}\)} + \assign{\(replies[27]\ \gets\ \{\ \)"{}Do\ you\ sometimes\ feel\ uneasy\ without\ a\ smartphone?"{}\(,\ \)"{}Have\ you\ had\ these\ phantasies\ before?"{}\(,\ \)"{}Does\ the\ world\ seem\ more\ real\ for\ you\ via\ apps?"{}\(\}\)} + \assign{\(replies[28]\ \gets\ \{\ \)"{}Tell\ me\ more\ about\ your\ family."{}\(,\ \)"{}Who\ else\ in\ your\ family*?"{}\(,\ \)"{}What\ does\ family\ relations\ mean\ for\ you?"{}\(,\ \)"{}Come\ on,\ How\ old\ are\ you?"{}\(\}\)} + \assign{\(setupReplies\ \gets\ replies\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(302,347)[ELIZA] + \assign{% + \begin{declaration}[Requires:] + \description{History, KeyMapEntry}{} + \end{declaration} + } + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*************\ ELIZA\ **************"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ Original\ design\ by\ J.\ Weizenbaum"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}**********************************"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ Adapted\ for\ Basic\ on\ IBM\ PC\ by"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ -\ Patricia\ Danielson"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ -\ Paul\ Hashfield"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}**********************************"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ Adapted\ for\ Structorizer\ by"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ -\ Kay\ G"urtzig\ /\ FH\ Erfurt\ 2016"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ Version:\ 2.3\ (2019-11-28)"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}*\ (Requires\ at\ least\ Structorizer\ 3.30-03\ to\ run)"{}\(\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}**********************************"{}\(\)} + \assign{\(history\ \gets\ History\{\{\)"{}"{}\(,\ \)"{}"{}\(,\ \)"{}"{}\(,\ \)"{}"{}\(,\ \)"{}"{}\(\},\ 0\}\)} + \sub{\(const\ replies\ \gets\ setupReplies()\)} + \sub{\(const\ reflexions\ \gets\ setupReflexions()\)} + \sub{\(const\ byePhrases\ \gets\ setupGoodByePhrases()\)} + \sub{\(const\ keyMap\ \gets\ setupKeywords()\)} + \assign{\(offsets[length(keyMap)-1]\ \gets\ 0\)} + \assign{\(isGone\ \gets\ false\)} + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}Hi!\ I\'{}m\ your\ new\ therapist.\ My\ name\ is\ Eliza.\ What\'{}s\ your\ problem?"{}\(\)} + \until{\(isGone\)} + \assign{\(\)\pKey{INPUT}\(\ userInput\)} + \sub{\(userInput\ \gets\ normalizeInput(userInput)\)} + \sub{\(isGone\ \gets\ checkGoodBye(userInput,\ byePhrases)\)} + \ifthenelse{5}{1}{\(!\ isGone\)}{ja}{nein} + \assign{\(reply\ \gets\ \)"{}Please\ don\'{}t\ repeat\ yourself!"{}\(\)} + \sub{\(isRepeated\ \gets\ checkRepetition(history,\ userInput)\)} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{3}{1}... + \ifthenelse{3}{1}{\(!\ isRepeated\)}{ja}{nein} + \sub{\(findInfo\ \gets\ findKeyword(keyMap,\ userInput)\)} + \assign{\(keyIndex\ \gets\ findInfo[0]\)} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{1}{1}... + \ifthenelse{1}{1}{\(keyIndex\ <\ 0\)}{ja}{nein} + \assign{\(keyIndex\ \gets\ length(keyMap)-1\)} + \change + \ifend + \assign{\(var\ entry:\ KeyMapEntry\ \gets\ keyMap[keyIndex]\)} + \assign{\(varPart\ \gets\ \)"{}"{}\(\)} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{1}{1}... + \ifthenelse{1}{1}{\(length(entry.keyword)\ >\ 0\)}{ja}{nein} + \sub{\(varPart\ \gets\ conjugateStrings(userInput,\ entry.keyword,\ findInfo[1],\ reflexions)\)} + \change + \ifend + \assign{\(replyRing\ \gets\ replies[entry.index]\)} + \assign{\(reply\ \gets\ replyRing[offsets[keyIndex]]\)} + \assign{\(offsets[keyIndex]\ \gets\ (offsets[keyIndex]\ +\ 1)\ \)\pKey{mod}\(\ length(replyRing)\)} + \assign{\(posAster\ \gets\ pos(\)"{}*"{}\(,\ reply)\)} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{1}{1}... + \ifthenelse{1}{1}{\(posAster\ >\ 0\)}{ja}{nein} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{1}{1}... + \ifthenelse{1}{1}{\(varPart\ =\ \)"{}\ "{}\(\)}{ja}{nein} + \assign{\(reply\ \gets\ \)"{}You\ will\ have\ to\ elaborate\ more\ for\ me\ to\ help\ you."{}\(\)} + \change + \assign{\(delete(reply,\ posAster,\ 1)\)} + \assign{\(insert(varPart,\ reply,\ posAster)\)} + \ifend + \change + \ifend + \sub{\(reply\ \gets\ adjustSpelling(reply)\)} + \change + \ifend + \assign{\(\)\pKey{OUTPUT}\(\ reply\)} + \change + \ifend + \untilend +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(152,39)[History] + \assign{% + \begin{declaration}[type:] + \description{History}{record\ \{\ histArray\ :\ array\ of\ string\ ;\ histIndex\ :\ int\ \}} + \end{declaration} + } +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(142,25)[KeyMapEntry] + \assign{% + \begin{declaration}[type:] + \description{KeyMapEntry}{record\ \{\ keyword\ :\ string\ ;\ index\ :\ int\ \}} + \end{declaration} + } +\end{struktogramm} + +\end{document} diff --git a/samples/export/StrukTeX/SORTING_TEST_MAIN.tex b/samples/export/StrukTeX/SORTING_TEST_MAIN.tex index c7ab4017..97202286 100644 --- a/samples/export/StrukTeX/SORTING_TEST_MAIN.tex +++ b/samples/export/StrukTeX/SORTING_TEST_MAIN.tex @@ -36,7 +36,7 @@ % TODO: Tune the width and height argument if necessary! -\begin{struktogramm}(178,109)[maxHeapify] +\begin{struktogramm}(175,109)[maxHeapify] \assign{% \begin{declaration}[Parameters:] \description{\pVar{heap}}{type: \(null\)} @@ -105,7 +105,7 @@ % TODO: Tune the width and height argument if necessary! -\begin{struktogramm}(130,69)[testSorted] +\begin{struktogramm}(131,69)[testSorted] \assign{% \begin{declaration}[Parameters:] \description{\pVar{numbers}}{type: \(null\)} @@ -128,7 +128,7 @@ % TODO: Tune the width and height argument if necessary! -\begin{struktogramm}(90,45)[buildMaxHeap] +\begin{struktogramm}(89,45)[buildMaxHeap] \assign{% \begin{declaration}[Parameters:] \description{\pVar{heap}}{type: \(null\)} @@ -142,7 +142,7 @@ % TODO: Tune the width and height argument if necessary! -\begin{struktogramm}(183,82)[quickSort] +\begin{struktogramm}(181,82)[quickSort] \assign{% \begin{declaration}[Parameters:] \description{\pVar{values}}{type: \(null\)} @@ -182,7 +182,7 @@ % TODO: Tune the width and height argument if necessary! -\begin{struktogramm}(248,204)[SORTING\_TEST\_MAIN] +\begin{struktogramm}(247,204)[SORTING\_TEST\_MAIN] \until{\(elementCount\ \geq\ 1\)} \assign{\(\)\pKey{INPUT}\(\ elementCount\)} \untilend diff --git a/samples/export/StrukTeX/TextDemo.tex b/samples/export/StrukTeX/TextDemo.tex new file mode 100644 index 00000000..30fef02b --- /dev/null +++ b/samples/export/StrukTeX/TextDemo.tex @@ -0,0 +1,1046 @@ +\documentclass[a4paper,10pt]{article} + +\usepackage{struktex} +\usepackage{german} +\usepackage{mathcomp} + +\title{Structorizer StrukTeX Export of TextWriter.arrz} +\author{Kay Gürtzig} +\date{03.12.2019} + +\begin{document} + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(44,28)[blank] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(penUp()\)} + \assign{\(right(90)\)} + \assign{\(forward(width)\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(92,33)[forward] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{len}}{type: \(null\)} + \description{\pVar{color}}{type: \(null\)} + \end{declaration} + } + \case{6}{11}{\(color\)}{1} + \assign{\(forward(len)\)} + \switch{2} + \assign{\(forward(len)\)} + \switch{3} + \assign{\(forward(len)\)} + \switch{4} + \assign{\(forward(len)\)} + \switch{5} + \assign{\(forward(len)\)} + \switch{6} + \assign{\(forward(len)\)} + \switch{7} + \assign{\(forward(len)\)} + \switch{8} + \assign{\(forward(len)\)} + \switch{9} + \assign{\(forward(len)\)} + \switch{10} + \assign{\(forward(len)\)} + \caseend +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(70,80)[letterA] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(hypo\ \gets\ sqrt(h*h\ +\ width*width/4.0)\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width/2.0/h))\)} + \assign{\(right(rotAngle)\)} + \sub{\(forward(hypo/2.0,\ colorNo)\)} + \assign{\(right(90\ -\ rotAngle)\)} + \sub{\(forward(width/2.0,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(width/2.0)\)} + \assign{\(penDown()\)} + \assign{\(left(90\ -\ rotAngle)\)} + \sub{\(forward(hypo/2.0,\ colorNo)\)} + \assign{\(left(2*rotAngle)\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(rotAngle)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(53,73)[letterE] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(right(90)\)} + \assign{\(penUp()\)} + \assign{\(forward(h/2.0)\)} + \assign{\(right(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(left(90)\)} + \assign{\(penUp()\)} + \assign{\(forward(h/2.0)\)} + \assign{\(left(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(53,70)[letterF] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(right(90)\)} + \assign{\(penUp()\)} + \assign{\(forward(h/2.0)\)} + \assign{\(right(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(left(90)\)} + \assign{\(penUp()\)} + \assign{\(forward(h/2.0)\)} + \assign{\(left(90)\)} + \assign{\(forward(width)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(53,71)[letterH] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(right(90)\)} + \assign{\(forward(width)\)} + \assign{\(right(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(h/2.0,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(width)\)} + \assign{\(left(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(h/2.0,\ colorNo)\)} + \assign{\(left(180)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(53,87)[letterI] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(penUp()\)} + \assign{\(right(90)\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \sub{\(forward(b,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(b/2.0)\)} + \assign{\(left(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(right(90)\)} + \assign{\(backward(b/2.0)\)} + \assign{\(penDown()\)} + \sub{\(forward(b,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward(b/2\ +\ c)\)} + \assign{\(left(90)\)} + \assign{\(backward(h)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(53,60)[letterK] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(diag\ \gets\ h/sqrt(2.0)\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(right(90)\)} + \assign{\(forward(width)\)} + \assign{\(right(135)\)} + \assign{\(penDown()\)} + \sub{\(forward(diag,\ colorNo)\)} + \assign{\(left(90)\)} + \sub{\(forward(diag,\ colorNo)\)} + \assign{\(left(135)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(53,44)[letterL] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(h)\)} + \assign{\(right(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(64,62)[letterM] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(hypo\ \gets\ sqrt(width*width\ +\ h*h)/2.0\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width/h))\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(2*rotAngle)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \sub{\(forward(-h,\ colorNo)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(64,61)[letterN] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(hypo\ \gets\ sqrt(width*width\ +\ h*h)\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width/h))\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(rotAngle)\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(h)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(53,74)[letterT] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(penUp()\)} + \assign{\(forward(h)\)} + \assign{\(penDown()\)} + \assign{\(right(90)\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(width/2.0)\)} + \assign{\(penDown()\)} + \assign{\(right(90)\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(left(90)\)} + \assign{\(penUp()\)} + \assign{\(forward(width/2.0)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(70,64)[letterV] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(hypo\ \gets\ sqrt(h*h\ +\ width*width/4.0)\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width/2.0/h))\)} + \assign{\(penUp()\)} + \assign{\(forward(h)\)} + \assign{\(left(rotAngle)\)} + \assign{\(penDown()\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(2*rotAngle)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(rotAngle)\)} + \assign{\(backward(h)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(68,96)[letterW] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(width\_3\ \gets\ width/3.0\)} + \assign{\(hypo\ \gets\ sqrt(width\_3*width\_3\ +\ h*h)\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width\_3/h))\)} + \assign{\(penUp()\)} + \assign{\(forward(h)\)} + \assign{\(left(rotAngle)\)} + \assign{\(penDown()\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(2*rotAngle)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(90+rotAngle)\)} + \assign{\(forward(width\_3)\)} + \assign{\(right(90-rotAngle)\)} + \assign{\(penDown()\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(2*rotAngle)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(rotAngle)\)} + \assign{\(backward(h)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(64,60)[letterX] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(hypo\ \gets\ sqrt(width*width\ +\ h*h)\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width/h))\)} + \assign{\(right(rotAngle)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(90+rotAngle)\)} + \assign{\(forward(width)\)} + \assign{\(right(90-rotAngle)\)} + \assign{\(penDown()\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(rotAngle)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(64,85)[letterY] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(hypo\ \gets\ sqrt(width*width\ +\ h*h)/2.0\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width/h))\)} + \assign{\(penUp()\)} + \assign{\(forward(h)\)} + \assign{\(left(rotAngle)\)} + \assign{\(penDown()\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(rotAngle)\)} + \assign{\(penUp()\)} + \assign{\(backward(h/2.0)\)} + \assign{\(penDown()\)} + \sub{\(forward(h/2.0,\ colorNo)\)} + \assign{\(right(rotAngle)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \assign{\(penUp()\)} + \assign{\(backward(h)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(64,68)[letterZ] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(hypo\ \gets\ sqrt(width*width\ +\ h*h)\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(width/h))\)} + \assign{\(penUp()\)} + \assign{\(forward(h)\)} + \assign{\(right(90)\)} + \assign{\(penDown()\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(left(90-rotAngle)\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(right(90-rotAngle)\)} + \sub{\(forward(width,\ colorNo)\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(134,46)[polygonPart] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{a}}{type: \(double\)} + \description{\pVar{n}}{type: \(integer\)} + \description{\pVar{ctrclkws}}{type: \(boolean\)} + \description{\pVar{nEdges}}{type: \(integer\)} + \description{\pVar{color}}{type: \(int\)} + \end{declaration} + } + \assign{\(rotAngle\ \gets\ 360.0/n\)} + % Reduce the ratio arguments or insert an optional height argument if the head got too flat, e.g.: \ifthenelse{3}{3}... or \ifthenelse[10]{10}{2}... + \ifthenelse{10}{2}{\(ctrclkws\)}{ja}{nein} + \assign{\(rotAngle\ \gets\ -rotAngle\)} + \change + \ifend + \while{\pKey{for}\(k\ \gets\ 1\)\pKey{to}\(nEdges\)} + \assign{\(right(rotAngle)\)} + \sub{\(forward(a,\ color)\)} + \whileend +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(65,74)[charDummy] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(width\ \gets\ h\ /\ 2.0\)} + \assign{\(b\ \gets\ width\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ (width\ -\ b)\ /\ 2.0\)} + \assign{\(d\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(penUp()\)} + \assign{\(forward(h/2.0-b/2.0)\)} + \assign{\(right(90)\)} + \assign{\(forward(c)\)} + \assign{\(right(90)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(b,\ 4,\ true,\ 4,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(90)\)} + \assign{\(forward(b\ +\ c)\)} + \assign{\(left(90)\)} + \assign{\(backward(h/2.0-b/2.0)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(65,98)[comma] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ toDegrees(atan(0.5))\)} + \assign{\(hypo\ \gets\ c\ *\ sqrt(1.25)\)} + \assign{\(penUp()\)} + \assign{\(right(90)\)} + \assign{\(forward((c+b)/2.0\ +\ c)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(c,\ 4,\ true,\ 3,\ colorNo)\)} + \assign{\(left(90)\)} + \sub{\(forward(c/2.0,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(left(180\ -\ rotAngle)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(right(90\ -\ rotAngle)\)} + \assign{\(forward((c\ +\ b)/2.0)\)} + \assign{\(left(90)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(84,138)[exclMk] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(width\ \gets\ h/2.0\)} + \assign{\(length1\ \gets\ h\ -\ (b+c)/2.0\)} + \assign{\(length2\ \gets\ length1\ -\ 2*c\)} + \assign{\(hypo\ \gets\ sqrt(width*width/16.0\ +\ length2*length2)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \assign{\(rotAngle2\ \gets\ toDegrees(atan(width/4.0/length2))\)} + \assign{\(penUp()\)} + \assign{\(forward(length1)\)} + \assign{\(right(90)\)} + \assign{\(forward(width/2.0)\)} + \assign{\(left(90\ +\ rotAngle)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(b/2.0,\ 8,\ false,\ 5,\ colorNo)\)} + \assign{\(right(rotAngle2)\)} + \sub{\(forward(hypo,\ colorNo)\)} + \assign{\(left(2*rotAngle2)\)} + \sub{\(forward(-hypo,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward(hypo)\)} + \assign{\(right(rotAngle2)\)} + \assign{\(forward(c)\)} + \assign{\(left(90)\)} + \assign{\(forward(c/2.0)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(c,\ 4,\ false,\ 4,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward((c\ +\ b)/2.0)\)} + \assign{\(left(90)\)} + \assign{\(backward(c)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(68,58)[fullSt] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(penUp()\)} + \assign{\(right(90)\)} + \assign{\(forward((c+b)/2.0\ +\ c)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(c,\ 4,\ true,\ 4,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward((c\ +\ b)/2.0)\)} + \assign{\(left(90)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(66,92)[letterB] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(c+b,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 4,\ colorNo)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(180)\)} + \assign{\(forward(b\ +\ c)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 4,\ colorNo)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(180)\)} + \assign{\(forward(b\ +\ 2*c)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(73,106)[letterC] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \assign{\(right(180)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 3,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \assign{\(penUp()\)} + \assign{\(forward(2*b\ +\ 2*c)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 4,\ colorNo)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(left(90)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(72,84)[letterD] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(c+b,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 2,\ colorNo)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 2,\ colorNo)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(left(180)\)} + \assign{\(forward(b\ +\ 2*c)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(69,113)[letterG] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \assign{\(right(180)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 4,\ colorNo)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(left(90)\)} + \sub{\(forward(b/2.0\ +\ c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(b/2.0\ +\ c)\)} + \assign{\(right(90)\)} + \assign{\(forward(b\ +\ c)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 4,\ colorNo)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(left(90)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(69,75)[letterJ] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \assign{\(right(180)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 3,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \sub{\(forward(h\ -\ c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(h)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(67,85)[letterO] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \assign{\(right(180)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 4,\ colorNo)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 4,\ colorNo)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(left(90)\)} + \assign{\(forward(b\ +\ 2*c)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(66,73)[letterP] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(c+b,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 4,\ colorNo)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(b\ +\ 2*c)\)} + \assign{\(left(90)\)} + \assign{\(forward(b\ +\ 2*c)\)} + \assign{\(penDown()\)} + \assign{\(left(180)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(67,103)[letterQ] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \assign{\(right(180)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 4,\ colorNo)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 4,\ colorNo)\)} + \sub{\(forward(b\ +\ 2*c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(left(90)\)} + \assign{\(forward(b\ +\ 2*c)\)} + \assign{\(right(rotAngle)\)} + \assign{\(backward(b)\)} + \assign{\(penDown()\)} + \sub{\(forward(b,\ colorNo)\)} + \assign{\(left(90\ +\ rotAngle)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(67,77)[letterR] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \sub{\(forward(h,\ colorNo)\)} + \assign{\(right(90)\)} + \sub{\(forward(c+b,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 4,\ colorNo)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(left(90\ +\ rotAngle)\)} + \sub{\(forward(sqrt(2.0)*(b\ +\ 2*c),\ colorNo)\)} + \assign{\(left(90\ +\ rotAngle)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(67,83)[letterS] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \assign{\(right(180)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 6,\ colorNo)\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 5,\ colorNo)\)} + \assign{\(right(rotAngle)\)} + \assign{\(penUp()\)} + \assign{\(forward(2*b\ +\ 3*c)\)} + \assign{\(penDown()\)} + \assign{\(left(180)\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(94,87)[letterU] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(penDown()\)} + \sub{\(forward(h\ -\ c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(h-c)\)} + \assign{\(penDown()\)} + \assign{\(right(180)\)} + \sub{\(polygonPart(b,\ 8,\ true,\ 3,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \sub{\(forward(h\ -\ c,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(backward(h)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(68,100)[qstnMk] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{h}}{type: \(null\)} + \description{\pVar{colorNo}}{type: \(null\)} + \end{declaration} + } + \assign{\(b\ \gets\ h\ *\ 0.5\ /\ (sqrt(2.0)\ +\ 1)\)} + \assign{\(c\ \gets\ b\ /\ sqrt(2.0)\)} + \assign{\(rotAngle\ \gets\ 45\)} + \assign{\(penUp()\)} + \assign{\(forward(h-c)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(b,\ 8,\ false,\ 5,\ colorNo)\)} + \sub{\(forward(c,\ colorNo)\)} + \assign{\(left(rotAngle)\)} + \sub{\(forward(b/2.0,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward(c)\)} + \assign{\(left(90)\)} + \assign{\(forward(c/2.0)\)} + \assign{\(penDown()\)} + \sub{\(polygonPart(c,\ 4,\ false,\ 4,\ colorNo)\)} + \assign{\(penUp()\)} + \assign{\(forward((c\ +\ b)/2.0)\)} + \assign{\(left(90)\)} + \assign{\(backward(c)\)} + \assign{\(penDown()\)} +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(333,107)[drawText] + \assign{% + \begin{declaration}[Parameters:] + \description{\pVar{text}}{type: \(string\)} + \description{\pVar{h}}{type: \(integer\)} + \description{\pVar{c}}{type: \(integer\)} + \end{declaration} + } + \assign{\(gap\ \gets\ h/10.0\)} + \while{\pKey{for}\(k\ \gets\ 1\)\pKey{to}\(length(text)\)} + \assign{\(letter\ \gets\ uppercase(copy(text,\ k,\ 1))\)} + \ifthenelse{1}{5}{\(letter\ =\ \)"{},"{}\(\)}{ja}{nein} + \sub{\(comma(h,c)\)} + \change + \case[155]{5}{31}{\(letter\)}{\)"{}A"{}\(} + \sub{\(letterA(h,c)\)} + \switch{\)"{}B"{}\(} + \sub{\(letterB(h,c)\)} + \switch{\)"{}C"{}\(} + \sub{\(letterC(h,c)\)} + \switch{\)"{}D"{}\(} + \sub{\(letterD(h,c)\)} + \switch{\)"{}E"{}\(} + \sub{\(letterE(h,c)\)} + \switch{\)"{}F"{}\(} + \sub{\(letterF(h,c)\)} + \switch{\)"{}G"{}\(} + \sub{\(letterG(h,c)\)} + \switch{\)"{}H"{}\(} + \sub{\(letterH(h,c)\)} + \switch{\)"{}I"{}\(} + \sub{\(letterI(h,c)\)} + \switch{\)"{}J"{}\(} + \sub{\(letterJ(h,c)\)} + \switch{\)"{}K"{}\(} + \sub{\(letterK(h,c)\)} + \switch{\)"{}L"{}\(} + \sub{\(letterL(h,c)\)} + \switch{\)"{}M"{}\(} + \sub{\(letterM(h,c)\)} + \switch{\)"{}N"{}\(} + \sub{\(letterN(h,c)\)} + \switch{\)"{}O"{}\(} + \sub{\(letterO(h,c)\)} + \switch{\)"{}P"{}\(} + \sub{\(letterP(h,c)\)} + \switch{\)"{}Q"{}\(} + \sub{\(letterQ(h,c)\)} + \switch{\)"{}R"{}\(} + \sub{\(letterR(h,c)\)} + \switch{\)"{}S"{}\(} + \sub{\(letterS(h,c)\)} + \switch{\)"{}T"{}\(} + \sub{\(letterT(h,c)\)} + \switch{\)"{}U"{}\(} + \sub{\(letterU(h,c)\)} + \switch{\)"{}V"{}\(} + \sub{\(letterV(h,c)\)} + \switch{\)"{}W"{}\(} + \sub{\(letterW(h,c)\)} + \switch{\)"{}X"{}\(} + \sub{\(letterX(h,c)\)} + \switch{\)"{}Y"{}\(} + \sub{\(letterY(h,c)\)} + \switch{\)"{}Z"{}\(} + \sub{\(letterZ(h,c)\)} + \switch{\)"{}\ "{}\(} + \sub{\(blank(h,c)\)} + \switch{\)"{}!"{}\(} + \sub{\(exclMk(h,c)\)} + \switch{\)"{}?"{}\(} + \sub{\(qstnMk(h,c)\)} + \switch{\)"{}."{}\(} + \sub{\(fullSt(h,c)\)} + \switch[r]{default} + \sub{\(charDummy(h,c)\)} + \caseend + \ifend + \assign{\(right(90)\)} + \assign{\(penUp()\)} + \assign{\(forward(gap)\)} + \assign{\(penDown()\)} + \assign{\(left(90)\)} + \whileend +\end{struktogramm} + + +% TODO: Tune the width and height argument if necessary! +\begin{struktogramm}(217,108)[TextDemo] + \assign{\(\)\pKey{OUTPUT}\(\ \)"{}This\ is\ a\ demo\ program\ for\ text\ writing\ with\ Turleizer."{}\(\)} + \assign{\(showTurtle()\)} + \assign{\(penDown()\)} + \assign{\(y\ \gets\ 0\)} + \until{\(text\ =\ \)"{}"{}\(\)} + \assign{\(\)\pKey{INPUT}\(\ \)"{}Enter\ some\ text\ (empty\ string\ to\ exit)"{}\(,\ text\)} + \assign{\(text\ \gets\ \)"{}"{}\(\ +\ text\)} + \ifthenelse{5}{1}{\(text\ \neq\ \)"{}"{}\(\)}{ja}{nein} + \until{\(height\ \geq\ 5\)} + \assign{\(\)\pKey{INPUT}\(\ \)"{}Height\ of\ the\ text\ (pixels)"{}\(,\ height\)} + \untilend + \until{\(colour\ \geq\ 1\ \wedge\ colour\ \leq\ 10\)} + \assign{\(\)\pKey{INPUT}\(\ \)"{}Colour\ (1=black,\ 2=red,\ 3=yellow,\ 4=green,\ 5=cyan,\ 6=blue,\ 7=pink,\ 8=gray,\ 9=orange,\ 10=violet)"{}\(,\ colour\)} + \untilend + \assign{\(y\ \gets\ y\ +\ height\ +\ 2\)} + \assign{\(gotoXY(0,\ y\ -\ 2)\)} + \sub{\(drawText(text,\ height,\ colour)\)} + \change + \ifend + \untilend + \assign{\(gotoXY(0,\ y\ +\ 15)\)} + \sub{\(drawText(\)"{}Thank\ you,\ bye."{}\(,\ 10,\ 4)\)} + \assign{\(hideTurtle()\)} +\end{struktogramm} + +\end{document} diff --git a/samples/export/bash/ELIZA_2.3.sh b/samples/export/bash/ELIZA_2.3.sh new file mode 100644 index 00000000..d23d5681 --- /dev/null +++ b/samples/export/bash/ELIZA_2.3.sh @@ -0,0 +1,478 @@ +#!/bin/bash + +# Concept and lisp implementation published by Joseph Weizenbaum (MIT): +# "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +# Computational Linguistis 1(1966)9, pp. 36-45 +# Revision history: +# 2016-10-06 Initial version +# 2017-03-29 Two diagrams updated (comments translated to English) +# 2017-03-29 More keywords and replies added +# 2019-03-14 Replies and mapping reorganised for easier maintenance +# 2019-03-15 key map joined from keyword array and index map +# 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +# 2019-11-28 New global type "History" (to ensure a homogenous array) +# (generated by Structorizer 3.30-03) +# +# Copyright (C) 2018-05-14 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# + +# Cares for correct letter case among others +adjustSpelling() { + sentence=$1 + +# TODO: Check and revise the syntax of all expressions! + + result=${sentence} + position=1 + + while [[ (${position} <= length(${sentence})) && (copy(${sentence}, ${position}, 1) == " ") ]] + do + position=$(( ${position} + 1 )) + done + + if [[ ${position} <= length(${sentence}) ]] + then + start=$(copy "${sentence}" $(1) "${position}") + delete "${result}" $(1) "${position}" + insert $(uppercase "${start}") "${result}" $(1) + fi + + for word in " i " " i\'" + do + position=$(pos "${word}" "${result}") + + while (( ${position} > 0 )) + do + delete "${result}" $(( ${position}+1 )) $(1) + insert $("I") "${result}" $(( ${position}+1 )) + position=$(pos "${word}" "${result}") + done + + done + +} + +# Checks whether the given text contains some kind of +# good-bye phrase inducing the end of the conversation +# and if so writes a correspding good-bye message and +# returns true, otherwise false +checkGoodBye() { + text=$1 + phrases=$2 + +# TODO: Check and revise the syntax of all expressions! + + for pair in ${phrases[@]} + do + + if [[ pos(${pair[0]}, ${text}) > 0 ]] + then + saidBye=1 + echo ${pair[1]} + return 1 + fi + + done + + return 0 +} + +# Checks whether newInput has occurred among the recently cached +# input strings in the histArray component of history and updates the history. +checkRepetition() { + history=$1 + newInput=$2 + +# TODO: Check and revise the syntax of all expressions! + +declare -A history +declare -A history + hasOccurred=0 + + if [[ length(${newInput}) > 4 ]] + then + histDepth=$(length $(${history[histArray]})) + + for (( i=0; i<=(( ${histDepth}-1 )); i++ )) + do + + if [[ ${newInput} == ${history[histArray]}[${i}] ]] + then + hasOccurred=1 + fi + + done + + history[histArray][history[histIndex]]=${newInput} + history[histIndex]=(${history[histIndex]} + 1) % (${histDepth}) + fi + + return ${hasOccurred} +} + +conjugateStrings() { + sentence=$1 + key=$2 + keyPos=$3 + flexions=$4 + +# TODO: Check and revise the syntax of all expressions! + + result=" " + copy(${sentence}, ${keyPos} + length(${key}), length(${sentence})) + " " + + for pair in ${flexions[@]} + do + left="" + right=${result} + position=$(pos $(${pair[0]}) "${right}") + + while (( ${position} > 0 )) + do + left=$(( ${left} + copy(${right}, 1, ${position}-1) + ${pair[1]} )) + right=$(copy "${right}" $(( ${position} + length(${pair[0]}) )) $(length "${right}")) + position=$(pos $(${pair[0]}) "${right}") + done + + result=$(( ${left} + ${right} )) + done + + # Eliminate multiple spaces + position=$(pos $(" ") "${result}") + + while (( ${position} > 0 )) + do + result=$(( copy(${result}, 1, ${position}-1) + copy(${result}, ${position}+1, length(${result})) )) + position=$(pos $(" ") "${result}") + done + +} + +# Looks for the occurrence of the first of the strings +# contained in keywords within the given sentence (in +# array order). +# Returns an array of +# 0: the index of the first identified keyword (if any, otherwise -1), +# 1: the position inside sentence (0 if not found) +findKeyword() { + keyMap=$1 + sentence=$2 + +# TODO: Check and revise the syntax of all expressions! + +declare -A entry + # Contains the index of the keyword and its position in sentence + declare -a result=($(( -1 )) $(0)) + i=0 + + while [[ (${result[0]} < 0) && (${i} < length(${keyMap})) ]] + do + entry=${keyMap[${i}]} + position=$(pos $(${entry[keyword]}) "${sentence}") + + if (( ${position} > 0 )) + then + result[0]=${i} + result[1]=${position} + fi + + i=$(( ${i}+1 )) + done + +} + +# Converts the sentence to lowercase, eliminates all +# interpunction (i.e. ',', '.', ';'), and pads the +# sentence among blanks +normalizeInput() { + sentence=$1 + +# TODO: Check and revise the syntax of all expressions! + + sentence=$(lowercase "${sentence}") + + for symbol in '.' ',' ';' '!' '?' + do + position=$(pos "${symbol}" "${sentence}") + + while (( ${position} > 0 )) + do + sentence=$(( copy(${sentence}, 1, ${position}-1) + copy(${sentence}, ${position}+1, length(${sentence})) )) + position=$(pos "${symbol}" "${sentence}") + done + + done + + result=" " + ${sentence} + " " +} + +setupGoodByePhrases() { + +# TODO: Check and revise the syntax of all expressions! + + declare -a phrases[0]=($(" shut") $("Okay. If you feel that way I\'ll shut up. ... Your choice.")) + declare -a phrases[1]=($("bye") $("Well, let\'s end our talk for now. See you later. Bye.")) + return ${phrases} +} + +# The lower the index the higher the rank of the keyword (search is sequential). +# The index of the first keyword found in a user sentence maps to a respective +# reply ring as defined in `setupReplies()´. +setupKeywords() { + +# TODO: Check and revise the syntax of all expressions! + + # The empty key string (last entry) is the default clause - will always be found + declare -a keywords[39]=([keyword]="" [index]=29) + declare -a keywords[0]=([keyword]="can you " [index]=0) + declare -a keywords[1]=([keyword]="can i " [index]=1) + declare -a keywords[2]=([keyword]="you are " [index]=2) + declare -a keywords[3]=([keyword]="you\'re " [index]=2) + declare -a keywords[4]=([keyword]="i don't " [index]=3) + declare -a keywords[5]=([keyword]="i feel " [index]=4) + declare -a keywords[6]=([keyword]="why don\'t you " [index]=5) + declare -a keywords[7]=([keyword]="why can\'t i " [index]=6) + declare -a keywords[8]=([keyword]="are you " [index]=7) + declare -a keywords[9]=([keyword]="i can\'t " [index]=8) + declare -a keywords[10]=([keyword]="i am " [index]=9) + declare -a keywords[11]=([keyword]="i\'m " [index]=9) + declare -a keywords[12]=([keyword]="you " [index]=10) + declare -a keywords[13]=([keyword]="i want " [index]=11) + declare -a keywords[14]=([keyword]="what " [index]=12) + declare -a keywords[15]=([keyword]="how " [index]=12) + declare -a keywords[16]=([keyword]="who " [index]=12) + declare -a keywords[17]=([keyword]="where " [index]=12) + declare -a keywords[18]=([keyword]="when " [index]=12) + declare -a keywords[19]=([keyword]="why " [index]=12) + declare -a keywords[20]=([keyword]="name " [index]=13) + declare -a keywords[21]=([keyword]="cause " [index]=14) + declare -a keywords[22]=([keyword]="sorry " [index]=15) + declare -a keywords[23]=([keyword]="dream " [index]=16) + declare -a keywords[24]=([keyword]="hello " [index]=17) + declare -a keywords[25]=([keyword]="hi " [index]=17) + declare -a keywords[26]=([keyword]="maybe " [index]=18) + declare -a keywords[27]=([keyword]=" no" [index]=19) + declare -a keywords[28]=([keyword]="your " [index]=20) + declare -a keywords[29]=([keyword]="always " [index]=21) + declare -a keywords[30]=([keyword]="think " [index]=22) + declare -a keywords[31]=([keyword]="alike " [index]=23) + declare -a keywords[32]=([keyword]="yes " [index]=24) + declare -a keywords[33]=([keyword]="friend " [index]=25) + declare -a keywords[34]=([keyword]="computer" [index]=26) + declare -a keywords[35]=([keyword]="bot " [index]=26) + declare -a keywords[36]=([keyword]="smartphone" [index]=27) + declare -a keywords[37]=([keyword]="father " [index]=28) + declare -a keywords[38]=([keyword]="mother " [index]=28) + return ${keywords} +} + +# Returns an array of pairs of mutualy substitutable +setupReflexions() { + +# TODO: Check and revise the syntax of all expressions! + + declare -a reflexions[0]=($(" are ") $(" am ")) + declare -a reflexions[1]=($(" were ") $(" was ")) + declare -a reflexions[2]=($(" you ") $(" I ")) + declare -a reflexions[3]=($(" your") $(" my")) + declare -a reflexions[4]=($(" i\'ve ") $(" you\'ve ")) + declare -a reflexions[5]=($(" i\'m ") $(" you\'re ")) + declare -a reflexions[6]=($(" me ") $(" you ")) + declare -a reflexions[7]=($(" my ") $(" your ")) + declare -a reflexions[8]=($(" i ") $(" you ")) + declare -a reflexions[9]=($(" am ") $(" are ")) + return ${reflexions} +} + +# This routine sets up the reply rings addressed by the key words defined in +# routine `setupKeywords()´ and mapped hitherto by the cross table defined +# in `setupMapping()´ +setupReplies() { + +# TODO: Check and revise the syntax of all expressions! + + # We start with the highest index for performance reasons + # (is to avoid frequent array resizing) + declare -a replies[29]=($("Say, do you have any psychological problems?") $("What does that suggest to you?") $("I see.") $("I'm not sure I understand you fully.") $("Come come elucidate your thoughts.") $("Can you elaborate on that?") $("That is quite interesting.")) + declare -a replies[0]=($("Don't you believe that I can*?") $("Perhaps you would like to be like me?") $("You want me to be able to*?")) + declare -a replies[1]=($("Perhaps you don't want to*?") $("Do you want to be able to*?")) + declare -a replies[2]=($("What makes you think I am*?") $("Does it please you to believe I am*?") $("Perhaps you would like to be*?") $("Do you sometimes wish you were*?")) + declare -a replies[3]=($("Don't you really*?") $("Why don't you*?") $("Do you wish to be able to*?") $("Does that trouble you*?")) + declare -a replies[4]=($("Do you often feel*?") $("Are you afraid of feeling*?") $("Do you enjoy feeling*?")) + declare -a replies[5]=($("Do you really believe I don't*?") $("Perhaps in good time I will*.") $("Do you want me to*?")) + declare -a replies[6]=($("Do you think you should be able to*?") $("Why can't you*?")) + declare -a replies[7]=($("Why are you interested in whether or not I am*?") $("Would you prefer if I were not*?") $("Perhaps in your fantasies I am*?")) + declare -a replies[8]=($("How do you know you can't*?") $("Have you tried?") $("Perhaps you can now*.")) + declare -a replies[9]=($("Did you come to me because you are*?") $("How long have you been*?") $("Do you believe it is normal to be*?") $("Do you enjoy being*?")) + declare -a replies[10]=($("We were discussing you--not me.") $("Oh, I*.") $("You're not really talking about me, are you?")) + declare -a replies[11]=($("What would it mean to you if you got*?") $("Why do you want*?") $("Suppose you soon got*...") $("What if you never got*?") $("I sometimes also want*.")) + declare -a replies[12]=($("Why do you ask?") $("Does that question interest you?") $("What answer would please you the most?") $("What do you think?") $("Are such questions on your mind often?") $("What is it that you really want to know?") $("Have you asked anyone else?") $("Have you asked such questions before?") $("What else comes to mind when you ask that?")) + declare -a replies[13]=($("Names don't interest me.") $("I don't care about names -- please go on.")) + declare -a replies[14]=($("Is that the real reason?") $("Don't any other reasons come to mind?") $("Does that reason explain anything else?") $("What other reasons might there be?")) + declare -a replies[15]=($("Please don't apologize!") $("Apologies are not necessary.") $("What feelings do you have when you apologize?") $("Don't be so defensive!")) + declare -a replies[16]=($("What does that dream suggest to you?") $("Do you dream often?") $("What persons appear in your dreams?") $("Are you disturbed by your dreams?")) + declare -a replies[17]=($("How do you do ...please state your problem.")) + declare -a replies[18]=($("You don't seem quite certain.") $("Why the uncertain tone?") $("Can't you be more positive?") $("You aren't sure?") $("Don't you know?")) + declare -a replies[19]=($("Are you saying no just to be negative?") $("You are being a bit negative.") $("Why not?") $("Are you sure?") $("Why no?")) + declare -a replies[20]=($("Why are you concerned about my*?") $("What about your own*?")) + declare -a replies[21]=($("Can you think of a specific example?") $("When?") $("What are you thinking of?") $("Really, always?")) + declare -a replies[22]=($("Do you really think so?") $("But you are not sure you*?") $("Do you doubt you*?")) + declare -a replies[23]=($("In what way?") $("What resemblance do you see?") $("What does the similarity suggest to you?") $("What other connections do you see?") $("Could there really be some connection?") $("How?") $("You seem quite positive.")) + declare -a replies[24]=($("Are you sure?") $("I see.") $("I understand.")) + declare -a replies[25]=($("Why do you bring up the topic of friends?") $("Do your friends worry you?") $("Do your friends pick on you?") $("Are you sure you have any friends?") $("Do you impose on your friends?") $("Perhaps your love for friends worries you.")) + declare -a replies[26]=($("Do computers worry you?") $("Are you talking about me in particular?") $("Are you frightened by machines?") $("Why do you mention computers?") $("What do you think machines have to do with your problem?") $("Don't you think computers can help people?") $("What is it about machines that worries you?")) + declare -a replies[27]=($("Do you sometimes feel uneasy without a smartphone?") $("Have you had these phantasies before?") $("Does the world seem more real for you via apps?")) + declare -a replies[28]=($("Tell me more about your family.") $("Who else in your family*?") $("What does family relations mean for you?") $("Come on, How old are you?")) + setupReplies=${replies} +} + + +# TODO: Check and revise the syntax of all expressions! + +declare -A history +declare -A entry +# Title information +echo "************* ELIZA **************" +echo "* Original design by J. Weizenbaum" +echo "**********************************" +echo "* Adapted for Basic on IBM PC by" +echo "* - Patricia Danielson" +echo "* - Paul Hashfield" +echo "**********************************" +echo "* Adapted for Structorizer by" +echo "* - Kay Gürtzig / FH Erfurt 2016" +echo "* Version: 2.3 (2019-11-28)" +echo "* (Requires at least Structorizer 3.30-03 to run)" +echo "**********************************" +# Stores the last five inputs of the user in a ring buffer, +# the second component is the rolling (over-)write index. +declare -a history=([histArray]={"", "", "", "", ""} [histIndex]=0) +replies=setupReplies +reflexions=setupReflexions +byePhrases=setupGoodByePhrases +keyMap=setupKeywords +offsets[length(${keyMap})-1]=0 +isGone=0 +# Starter +echo "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?" + +# NOTE: This is an automatically inserted copy of the loop body below. +read userInput +# Converts the input to lowercase, cuts out interpunctation +# and pads the string +userInput=normalizeInput "${userInput}" +isGone=checkGoodBye "${userInput}" "${byePhrases}" + +if [[ ! ${isGone} ]] +then + reply="Please don\'t repeat yourself!" + isRepeated=checkRepetition "${history}" "${userInput}" + + if [[ ! ${isRepeated} ]] + then + findInfo=findKeyword "${keyMap}" "${userInput}" + keyIndex=${findInfo[0]} + + if [[ ${keyIndex} < 0 ]] + then + # Should never happen... + keyIndex=$(( length(${keyMap})-1 )) + fi + + entry=${keyMap[${keyIndex}]} + # Variable part of the reply + varPart="" + + if [[ length(${entry[keyword]}) > 0 ]] + then + varPart=conjugateStrings "${userInput}" $(${entry[keyword]}) $(${findInfo[1]}) "${reflexions}" + fi + + replyRing=${replies[${entry[index]}]} + reply=${replyRing[${offsets[${keyIndex}]}]} + offsets[${keyIndex}]=(${offsets[${keyIndex}]} + 1) % length(${replyRing}) + posAster=$(pos $("*") "${reply}") + + if (( ${posAster} > 0 )) + then + + if [[ ${varPart} == " " ]] + then + reply="You will have to elaborate more for me to help you." + + else + delete "${reply}" "${posAster}" $(1) + insert "${varPart}" "${reply}" "${posAster}" + fi + + fi + + reply=adjustSpelling "${reply}" + fi + + echo ${reply} +fi + +while [[ ${isGone} ]] +do + read userInput + # Converts the input to lowercase, cuts out interpunctation + # and pads the string + userInput=normalizeInput "${userInput}" + isGone=checkGoodBye "${userInput}" "${byePhrases}" + + if [[ ! ${isGone} ]] + then + reply="Please don\'t repeat yourself!" + isRepeated=checkRepetition "${history}" "${userInput}" + + if [[ ! ${isRepeated} ]] + then + findInfo=findKeyword "${keyMap}" "${userInput}" + keyIndex=${findInfo[0]} + + if [[ ${keyIndex} < 0 ]] + then + # Should never happen... + keyIndex=$(( length(${keyMap})-1 )) + fi + + entry=${keyMap[${keyIndex}]} + # Variable part of the reply + varPart="" + + if [[ length(${entry[keyword]}) > 0 ]] + then + varPart=conjugateStrings "${userInput}" $(${entry[keyword]}) $(${findInfo[1]}) "${reflexions}" + fi + + replyRing=${replies[${entry[index]}]} + reply=${replyRing[${offsets[${keyIndex}]}]} + offsets[${keyIndex}]=(${offsets[${keyIndex}]} + 1) % length(${replyRing}) + posAster=$(pos $("*") "${reply}") + + if (( ${posAster} > 0 )) + then + + if [[ ${varPart} == " " ]] + then + reply="You will have to elaborate more for me to help you." + + else + delete "${reply}" "${posAster}" $(1) + insert "${varPart}" "${reply}" "${posAster}" + fi + + fi + + reply=adjustSpelling "${reply}" + fi + + echo ${reply} + fi + +done + diff --git a/samples/export/bash/SORTING_TEST_MAIN.sh b/samples/export/bash/SORTING_TEST_MAIN.sh index 1d461b1f..30fe47ed 100644 --- a/samples/export/bash/SORTING_TEST_MAIN.sh +++ b/samples/export/bash/SORTING_TEST_MAIN.sh @@ -4,7 +4,7 @@ # to allow performance comparison via execution counting ("Collect Runtime Data" should # sensibly be switched on). # Requested input data are: Number of elements (size) and filing mode. -# (generated by Structorizer 3.30-02) +# (generated by Structorizer 3.30-03) # # Copyright (C) 2019-10-02 Kay Gürtzig # License: GPLv3-link @@ -99,7 +99,7 @@ maxHeapify() { temp=${heap[${i}]} heap[${i}]=${heap[${max}]} heap[${max}]=${temp} - maxHeapify $(${heap}) $(${max}) $(${range}) + maxHeapify "${heap}" "${max}" "${range}" fi } @@ -190,11 +190,11 @@ buildMaxHeap() { # TODO: Check and revise the syntax of all expressions! - lgth=$(length $(${heap})) + lgth=$(length "${heap}") for (( k=(( ${lgth} / 2 - 1 )); k>=0; k-- )) do - maxHeapify $(${heap}) $(${k}) $(${lgth}) + maxHeapify "${heap}" "${k}" "${lgth}" done } @@ -217,23 +217,23 @@ quickSort() { p=$(( random(${stop}-${start}) + ${start} )) # Partition the array into smaller and greater elements # Get the resulting (and final) position of the pivot element - p=$(partition $(${values}) $(${start}) $(${stop}) $(${p})) + p=partition "${values}" "${start}" "${stop}" "${p}" # Sort subsequances separately and independently ... # ========================================================== # ================= START PARALLEL SECTION ================= # ========================================================== - pids3dfab37d="" + pids7fed1521="" ( # Sort left (lower) array part - quickSort $(${values}) $(${start}) $(${p}) + quickSort "${values}" "${start}" "${p}" ) & - pids3dfab37d="${pids3dfab37d} $!" + pids7fed1521="${pids7fed1521} $!" ( # Sort right (higher) array part - quickSort $(${values}) $(( ${p}+1 )) $(${stop}) + quickSort "${values}" $(( ${p}+1 )) "${stop}" ) & - pids3dfab37d="${pids3dfab37d} $!" - wait ${pids3dfab37d} + pids7fed1521="${pids7fed1521} $!" + wait ${pids7fed1521} # ========================================================== # ================== END PARALLEL SECTION ================== # ========================================================== @@ -248,8 +248,8 @@ heapSort() { # TODO: Check and revise the syntax of all expressions! - buildMaxHeap $(${values}) - heapRange=$(length $(${values})) + buildMaxHeap "${values}" + heapRange=$(length "${values}") for (( k=(( ${heapRange} - 1 )); k>=1; k-- )) do @@ -258,7 +258,7 @@ heapSort() { maximum=${values[0]} values[0]=${values[${heapRange}]} values[${heapRange}]=${maximum} - maxHeapify $(${values}) $(0) $(${heapRange}) + maxHeapify "${values}" $(0) "${heapRange}" done } @@ -300,7 +300,7 @@ do done -# Kopiere das Array für exakte Vergleichbarkeit +# Copy the array for exact comparability for (( i=0; i<=(( ${elementCount}-1 )); i++ )) do values2[${i}]=${values1[${i}]} @@ -310,26 +310,26 @@ done # ========================================================== # ================= START PARALLEL SECTION ================= # ========================================================== -pids4f085546="" +pids247e34b9="" ( - bubbleSort $(${values1}) + bubbleSort "${values1}" ) & -pids4f085546="${pids4f085546} $!" +pids247e34b9="${pids247e34b9} $!" ( - quickSort $(${values2}) $(0) $(${elementCount}) + quickSort "${values2}" $(0) "${elementCount}" ) & -pids4f085546="${pids4f085546} $!" +pids247e34b9="${pids247e34b9} $!" ( - heapSort $(${values3}) + heapSort "${values3}" ) & -pids4f085546="${pids4f085546} $!" -wait ${pids4f085546} +pids247e34b9="${pids247e34b9} $!" +wait ${pids247e34b9} # ========================================================== # ================== END PARALLEL SECTION ================== # ========================================================== -ok1=$(testSorted $(${values1})) -ok2=$(testSorted $(${values2})) -ok3=$(testSorted $(${values3})) +ok1=testSorted "${values1}" +ok2=testSorted "${values2}" +ok3=testSorted "${values3}" if [[ ! ${ok1} || ! ${ok2} || ! ${ok3} ]] then diff --git a/samples/export/bash/TextDemo.sh b/samples/export/bash/TextDemo.sh new file mode 100644 index 00000000..fb6db79a --- /dev/null +++ b/samples/export/bash/TextDemo.sh @@ -0,0 +1,1256 @@ +#!/bin/bash + +# Demo program for routine drawText() +# Asks the user to enter a text, a wanted text height and colour, +# and then draws this string onto the turtle screen. Places every +# entered text to a new line. +# (generated by Structorizer 3.30-03) +# +# Copyright (C) 2019-10-10 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# + +# Draws a blank for font height h, ignoring the colorNo +blank() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + penUp + right $(90) + forward "${width}" # color = ffffff + left $(90) +} + +forward() { + len=$1 + color=$2 + +# TODO: Check and revise the syntax of all expressions! + + case ${color} in + + 1) + forward "${len}" # color = ffffff + ;; + + 2) + forward "${len}" # color = ff8080 + ;; + + 3) + forward "${len}" # color = ffff80 + ;; + + 4) + forward "${len}" # color = 80ff80 + ;; + + 5) + forward "${len}" # color = 80ffff + ;; + + 6) + forward "${len}" # color = 0080ff + ;; + + 7) + forward "${len}" # color = ff80c0 + ;; + + 8) + forward "${len}" # color = c0c0c0 + ;; + + 9) + forward "${len}" # color = ff8000 + ;; + + 10) + forward "${len}" # color = 8080ff + ;; + esac + +} + +# Draws letter A in colour specified by colorNo with font height h +# from the current turtle position. +letterA() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${h}*${h} + ${width}*${width}/4.0 ))) + rotAngle=$(toDegrees $(atan $(( ${width}/2.0/${h} )))) + right "${rotAngle}" + forward $(( ${hypo}/2.0 )) "${colorNo}" + right $(( 90 - ${rotAngle} )) + forward $(( ${width}/2.0 )) "${colorNo}" + penUp + backward $(( ${width}/2.0 )) # color = ffffff + penDown + left $(( 90 - ${rotAngle} )) + forward $(( ${hypo}/2.0 )) "${colorNo}" + left $(( 2*${rotAngle} )) + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" +} + +# Draws letter E in colour specified by colorNo with font height h +# from the current turtle position. +letterE() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + right $(90) + forward "${width}" "${colorNo}" + right $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + left $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) +} + +# Draws letter F in colour specified by colorNo with font height h +# from the current turtle position. +letterF() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + right $(90) + forward "${width}" "${colorNo}" + right $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + left $(90) + forward "${width}" # color = ffffff + penDown + left $(90) +} + +# Draws letter H in colour specified by colorNo with font height h +# from the current turtle position. +letterH() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + penUp + right $(90) + forward "${width}" # color = ffffff + right $(90) + penDown + forward $(( ${h}/2.0 )) "${colorNo}" + right $(90) + forward "${width}" "${colorNo}" + penUp + backward "${width}" # color = ffffff + left $(90) + penDown + forward $(( ${h}/2.0 )) "${colorNo}" + left $(180) +} + +# Draws letter I in colour specified by colorNo with font height h +# from the current turtle position. +letterI() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( ${b} / sqrt(2.0) )) + penUp + right $(90) + forward "${c}" # color = ffffff + penDown + forward "${b}" "${colorNo}" + penUp + backward $(( ${b}/2.0 )) # color = ffffff + left $(90) + penDown + forward "${h}" "${colorNo}" + penUp + right $(90) + backward $(( ${b}/2.0 )) # color = ffffff + penDown + forward "${b}" "${colorNo}" + penUp + forward $(( ${b}/2 + ${c} )) # color = ffffff + left $(90) + backward "${h}" # color = ffffff + penDown +} + +# Draws letter K in colour specified by colorNo with font height h +# from the current turtle position. +letterK() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + diag=$(( ${h}/sqrt(2.0) )) + forward "${h}" "${colorNo}" + penUp + right $(90) + forward "${width}" # color = ffffff + right $(135) + penDown + forward "${diag}" "${colorNo}" + left $(90) + forward "${diag}" "${colorNo}" + left $(135) +} + +# Draws letter L in colour specified by colorNo with font height h +# from the current turtle position. +letterL() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + penUp + backward "${h}" # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) +} + +# Draws letter M in colour specified by colorNo with font height h +# from the current turtle position. +letterM() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(( sqrt(${width}*${width} + ${h}*${h})/2.0 )) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + forward "${h}" "${colorNo}" + left "${rotAngle}" + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + left "${rotAngle}" + forward $(( -${h} )) "${colorNo}" +} + +# Draws letter N in colour specified by colorNo with font height h +# from the current turtle position. +letterN() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${width}*${width} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + forward "${h}" "${colorNo}" + left "${rotAngle}" + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" + forward "${h}" "${colorNo}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws letter T in colour specified by colorNo with font height h +# from the current turtle position. +letterT() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + penUp + forward "${h}" # color = ffffff + penDown + right $(90) + forward "${width}" "${colorNo}" + penUp + backward $(( ${width}/2.0 )) # color = ffffff + penDown + right $(90) + forward "${h}" "${colorNo}" + left $(90) + penUp + forward $(( ${width}/2.0 )) # color = ffffff + penDown + left $(90) +} + +# Draws letter V in colour specified by colorNo with font height h +# from the current turtle position. +letterV() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${h}*${h} + ${width}*${width}/4.0 ))) + rotAngle=$(toDegrees $(atan $(( ${width}/2.0/${h} )))) + penUp + forward "${h}" # color = ffffff + left "${rotAngle}" + penDown + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + left "${rotAngle}" + backward "${h}" # color = ffffff + penDown +} + +# Draws letter W in colour specified by colorNo with font height h +# from the current turtle position. +letterW() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + width_3=$(( ${width}/3.0 )) + hypo=$(sqrt $(( ${width_3}*${width_3} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width_3}/${h} )))) + penUp + forward "${h}" # color = ffffff + left "${rotAngle}" + penDown + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + left $(( 90+${rotAngle} )) + forward "${width_3}" # color = ffffff + right $(( 90-${rotAngle} )) + penDown + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + left "${rotAngle}" + backward "${h}" # color = ffffff + penDown +} + +# Draws letter X in colour specified by colorNo with font height h +# from the current turtle position. +letterX() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${width}*${width} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + right "${rotAngle}" + forward "${hypo}" "${colorNo}" + penUp + left $(( 90+${rotAngle} )) + forward "${width}" # color = ffffff + right $(( 90-${rotAngle} )) + penDown + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" +} + +# Draws letter Y in colour specified by colorNo with font height h +# from the current turtle position. +letterY() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(( sqrt(${width}*${width} + ${h}*${h})/2.0 )) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + penUp + forward "${h}" # color = ffffff + left "${rotAngle}" + penDown + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" + penUp + backward $(( ${h}/2.0 )) # color = ffffff + penDown + forward $(( ${h}/2.0 )) "${colorNo}" + right "${rotAngle}" + forward "${hypo}" "${colorNo}" + left "${rotAngle}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws letter Z in colour specified by colorNo with font height h +# from the current turtle position. +letterZ() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${width}*${width} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + penUp + forward "${h}" # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(( 90-${rotAngle} )) + forward $(( -${hypo} )) "${colorNo}" + right $(( 90-${rotAngle} )) + forward "${width}" "${colorNo}" + left $(90) +} + +# Draws nEdges edges of a regular n-polygon with edge length a +# counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +polygonPart() { + a=$1 + n=$2 + ctrclkws=$3 + nEdges=$4 + color=$5 + +# TODO: Check and revise the syntax of all expressions! + + rotAngle=$(( 360.0/${n} )) + + if [[ ${ctrclkws} ]] + then + rotAngle=$(( -${rotAngle} )) + fi + + for (( k=1; k<=${nEdges}; k++ )) + do + right "${rotAngle}" + forward "${a}" "${color}" + done + +} + +# Draws a dummy character (small centered square) with font height h and +# the colour encoded by colorNo +charDummy() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h} / 2.0 )) + # Octagon edge length (here: edge lengzh of the square) + b=$(( ${width} / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( (${width} - ${b}) / 2.0 )) + d=$(( ${b} / sqrt(2.0) )) + penUp + forward $(( ${h}/2.0-${b}/2.0 )) # color = ffffff + right $(90) + forward "${c}" # color = ffffff + right $(90) + penDown + # Draws the square with edge length b + polygonPart "${b}" $(4) $(1) $(4) "${colorNo}" + penUp + left $(90) + forward $(( ${b} + ${c} )) # color = ffffff + left $(90) + backward $(( ${h}/2.0-${b}/2.0 )) # color = ffffff + penDown +} + +# Draws a comma in colour specified by colorNo with font height h +# from the current turtle position. +comma() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + rotAngle=$(toDegrees $(atan $(0.5))) + hypo=$(( ${c} * sqrt(1.25) )) + penUp + right $(90) + forward $(( (${c}+${b})/2.0 + ${c} )) # color = ffffff + penDown + # Counterclockwise draw 3 edges of a square with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(1) $(3) "${colorNo}" + left $(90) + forward $(( ${c}/2.0 )) "${colorNo}" + right $(90) + forward "${c}" "${colorNo}" + left $(( 180 - ${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + right $(( 90 - ${rotAngle} )) + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + penDown +} + +# Draws an exclamation mark in the colour encoded by colorNo with font height h +# from the current turtle position. +exclMk() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + width=$(( ${h}/2.0 )) + length1=$(( ${h} - (${b}+${c})/2.0 )) + length2=$(( ${length1} - 2*${c} )) + hypo=$(sqrt $(( ${width}*${width}/16.0 + ${length2}*${length2} ))) + # 360°/8 + rotAngle=45 + rotAngle2=$(toDegrees $(atan $(( ${width}/4.0/${length2} )))) + penUp + forward "${length1}" # color = ffffff + right $(90) + forward $(( ${width}/2.0 )) # color = ffffff + left $(( 90 + ${rotAngle} )) + penDown + # Clockwise draw 5 edges of an octagon with edge length b/2 + # in the colour endcoded by colorNo + polygonPart $(( ${b}/2.0 )) $(8) $(0) $(5) "${colorNo}" + right "${rotAngle2}" + forward "${hypo}" "${colorNo}" + left $(( 2*${rotAngle2} )) + forward $(( -${hypo} )) "${colorNo}" + penUp + forward "${hypo}" # color = ffffff + right "${rotAngle2}" + forward "${c}" # color = ffffff + left $(90) + forward $(( ${c}/2.0 )) # color = ffffff + penDown + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(0) $(4) "${colorNo}" + penUp + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + backward "${c}" # color = ffffff + penDown +} + +# Draws a full stop in colour specified by colorNo with font height h +# from the current turtle position. +fullSt() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + penUp + right $(90) + forward $(( (${c}+${b})/2.0 + ${c} )) # color = ffffff + penDown + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(1) $(4) "${colorNo}" + penUp + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + penDown +} + +# Draws letter B in colour specified by colorNo with font height h +# from the current turtle position. +letterB() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the outer corner triangle of the octagon + c=$(( ${b} / sqrt(2.0) )) + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + left $(180) + forward $(( ${b} + ${c} )) # color = ffffff + penDown + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + left $(180) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(90) +} + +# Draws letter C in the colour encoded by colorNo with font height h +# from the current turtle position. +letterC() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the outer trinagle at the octagon corner + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Clockwise draws 3 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart "${b}" $(8) $(1) $(3) "${colorNo}" + left "${rotAngle}" + penUp + forward $(( 2*${b} + 2*${c} )) # color = ffffff + penDown + # Counterclockwise draws 4 edges of an octagon with edge length b + # iin the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) "${colorNo}" + penDown + left $(90) +} + +# Draws letter D in colour specified by colorNo with font height h +# from the current turtle position. +letterD() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart "${b}" $(8) $(0) $(2) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart "${b}" $(8) $(0) $(2) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + left $(180) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(90) +} + +# Draws letter G in colour specified by colorNo with font height h +# from the current turtle position. +letterG() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon. + c=$(( ${b} / sqrt(2.0) )) + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + left $(90) + forward $(( ${b}/2.0 + ${c} )) "${colorNo}" + penUp + backward $(( ${b}/2.0 + ${c} )) # color = ffffff + right $(90) + forward $(( ${b} + ${c} )) # color = ffffff + penDown + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) "${colorNo}" + penDown + left $(90) +} + +# Draws letter J in colour encoded by colorNo with font height h +# from the current turtle position. +letterJ() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 3 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(3) "${colorNo}" + left "${rotAngle}" + forward $(( ${h} - ${c} )) "${colorNo}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws letter O in colour specified by colorNo with font height h +# from the current turtle position. +letterO() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( ${b} / sqrt(2.0) )) + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(90) +} + +# Draws letter P in colour specified by colorNo with font height h +# from the current turtle position. +letterP() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( ${b} / sqrt(2.0) )) + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + backward $(( ${b} + 2*${c} )) # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(180) +} + +# Draws letter Q in colour specified by colorNo with font height h +# from the current turtle position. +letterQ() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) # color = ffffff + right "${rotAngle}" + backward "${b}" # color = ffffff + penDown + forward "${b}" "${colorNo}" + left $(( 90 + ${rotAngle} )) +} + +# Zeichnet den Buchstaben R von der Turtleposition aus +# mit Zeilenhöhe h +letterR() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + left $(( 90 + ${rotAngle} )) + forward $(( sqrt(2.0)*(${b} + 2*${c}) )) "${colorNo}" + left $(( 90 + ${rotAngle} )) +} + +# Draws letter S in colour specified by colorNo with font height h +# from the current turtle position. +letterS() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 6 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(6) "${colorNo}" + # Clockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(5) "${colorNo}" + right "${rotAngle}" + penUp + forward $(( 2*${b} + 3*${c} )) # color = ffffff + penDown + left $(180) +} + +# Draws letter U in colour specified by colorNo with font height h +# from the current turtle position. +letterU() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # edge length of a regular octagon + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + forward $(( ${h} - ${c} )) "${colorNo}" + penUp + backward $(( ${h}-${c} )) # color = ffffff + penDown + right $(180) + # Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart "${b}" $(8) $(1) $(3) "${colorNo}" + left "${rotAngle}" + forward $(( ${h} - ${c} )) "${colorNo}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws a question mark in colour specified by colorNo with font height h +# from the current turtle position. +qstnMk() { + h=$1 + colorNo=$2 + +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward $(( ${h}-${c} )) # color = ffffff + penDown + # Counterclockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(5) "${colorNo}" + forward "${c}" "${colorNo}" + left "${rotAngle}" + forward $(( ${b}/2.0 )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${c}/2.0 )) # color = ffffff + penDown + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(0) $(4) "${colorNo}" + penUp + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + backward "${c}" # color = ffffff + penDown +} + +# Has the turtle draw the given string 'text´ with font height 'h´ (in +# pixels) and the colour coded by integer 'c´ from the current Turtle +# position to the Turtle canvas. If the turtle looks North then +# the text will be written rightwards. In the event, the turtle will be +# placed behind the text in original orientation (such that the next text +# would be written like a continuation. Colour codes: +# 1 = black +# 2 = red +# 3 = yellow +# 4 = green +# 5 = cyan +# 6 = blue +# 7 = pink +# 8 = grey +# 9 = orange +# 10 = violet +# All letters (ASCII) will be converted to uppercase, digits cannot +# be represented, the set of representable special characters is: +# '.', ',', '!', '?'. Other characters will be shown as a small +# centred square (dummy character). +drawText() { + text=$1 + h=$2 + c=$3 + +# TODO: Check and revise the syntax of all expressions! + + gap=$(( ${h}/10.0 )) + + for (( k=1; k<=length "${text}"; k++ )) + do + letter=$(uppercase $(copy "${text}" "${k}" $(1))) + + if [[ ${letter} == "," ]] + then + comma "${h}" "${c}" + + else + + # "," cannot be chacked against because the comma is misinterpreted + # as selector list separator. + case ${letter} in + + "A") + letterA "${h}" "${c}" + ;; + + "B") + letterB "${h}" "${c}" + ;; + + "C") + letterC "${h}" "${c}" + ;; + + "D") + letterD "${h}" "${c}" + ;; + + "E") + letterE "${h}" "${c}" + ;; + + "F") + letterF "${h}" "${c}" + ;; + + "G") + letterG "${h}" "${c}" + ;; + + "H") + letterH "${h}" "${c}" + ;; + + "I") + letterI "${h}" "${c}" + ;; + + "J") + letterJ "${h}" "${c}" + ;; + + "K") + letterK "${h}" "${c}" + ;; + + "L") + letterL "${h}" "${c}" + ;; + + "M") + letterM "${h}" "${c}" + ;; + + "N") + letterN "${h}" "${c}" + ;; + + "O") + letterO "${h}" "${c}" + ;; + + "P") + letterP "${h}" "${c}" + ;; + + "Q") + letterQ "${h}" "${c}" + ;; + + "R") + letterR "${h}" "${c}" + ;; + + "S") + letterS "${h}" "${c}" + ;; + + "T") + letterT "${h}" "${c}" + ;; + + "U") + letterU "${h}" "${c}" + ;; + + "V") + letterV "${h}" "${c}" + ;; + + "W") + letterW "${h}" "${c}" + ;; + + "X") + letterX "${h}" "${c}" + ;; + + "Y") + letterY "${h}" "${c}" + ;; + + "Z") + letterZ "${h}" "${c}" + ;; + + " ") + blank "${h}" "${c}" + ;; + + "!") + exclMk "${h}" "${c}" + ;; + + "?") + qstnMk "${h}" "${c}" + ;; + + ".") + fullSt "${h}" "${c}" + ;; + + *) + charDummy "${h}" "${c}" + ;; + esac + + fi + + right $(90) + penUp + forward "${gap}" # color = ffffff + penDown + left $(90) + done + +} + + +# TODO: Check and revise the syntax of all expressions! + +echo "This is a demo program for text writing with Turleizer." +showTurtle +penDown +y=0 + +# NOTE: This is an automatically inserted copy of the loop body below. +echo -n "Enter some text (empty string to exit)" ; read text +# Make sure the content is interpreted as string +text=$(( "" + ${text} )) + +if [[ ${text} != "" ]] +then + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Height of the text (pixels)" ; read height + while [[ ${height} >= 5 ]] + do + echo -n "Height of the text (pixels)" ; read height + done + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + while [[ ${colour} >= 1 && ${colour} <= 10 ]] + do + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + done + + y=$(( ${y} + ${height} + 2 )) + gotoXY $(0) $(( ${y} - 2 )) + drawText "${text}" "${height}" "${colour}" +fi + +while [[ ${text} == "" ]] +do + echo -n "Enter some text (empty string to exit)" ; read text + # Make sure the content is interpreted as string + text=$(( "" + ${text} )) + + if [[ ${text} != "" ]] + then + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Height of the text (pixels)" ; read height + while [[ ${height} >= 5 ]] + do + echo -n "Height of the text (pixels)" ; read height + done + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + while [[ ${colour} >= 1 && ${colour} <= 10 ]] + do + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + done + + y=$(( ${y} + ${height} + 2 )) + gotoXY $(0) $(( ${y} - 2 )) + drawText "${text}" "${height}" "${colour}" + fi + +done + +gotoXY $(0) $(( ${y} + 15 )) +drawText $("Thank you, bye.") $(10) $(4) +hideTurtle diff --git a/samples/export/ksh/ELIZA_2.3.ksh b/samples/export/ksh/ELIZA_2.3.ksh new file mode 100644 index 00000000..d2816272 --- /dev/null +++ b/samples/export/ksh/ELIZA_2.3.ksh @@ -0,0 +1,461 @@ +#!/usr/bin/ksh +# Generated by Structorizer 3.30-03 +# +# Copyright (C) 2018-05-14 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# + +# Cares for correct letter case among others +adjustSpelling() { + sentence=$1 +# TODO: Check and revise the syntax of all expressions! + + result=${sentence} + position=1 + + while [[ (${position} <= length(${sentence})) && (copy(${sentence}, ${position}, 1) == " ") ]] + do + position=$(( ${position} + 1 )) + done + + if [[ ${position} <= length(${sentence}) ]] + then + start=$(copy "${sentence}" $(1) "${position}") + delete "${result}" $(1) "${position}" + insert $(uppercase "${start}") "${result}" $(1) + fi + + for word in " i " " i\'" + do + position=$(pos "${word}" "${result}") + + while (( ${position} > 0 )) + do + delete "${result}" $(( ${position}+1 )) $(1) + insert $("I") "${result}" $(( ${position}+1 )) + position=$(pos "${word}" "${result}") + done + + done + +} + +# Checks whether the given text contains some kind of +# good-bye phrase inducing the end of the conversation +# and if so writes a correspding good-bye message and +# returns true, otherwise false +checkGoodBye() { + text=$1 + phrases=$2 +# TODO: Check and revise the syntax of all expressions! + + for pair in ${phrases[@]} + do + + if [[ pos(${pair[0]}, ${text}) > 0 ]] + then + saidBye=1 + echo ${pair[1]} + return 1 + fi + + done + + return 0 +} + +# Checks whether newInput has occurred among the recently cached +# input strings in the histArray component of history and updates the history. +checkRepetition() { + history=$1 + newInput=$2 +# TODO: Check and revise the syntax of all expressions! + + hasOccurred=0 + + if [[ length(${newInput}) > 4 ]] + then + histDepth=$(length $(${history[histArray]})) + + for (( i=0; i<=(( ${histDepth}-1 )); i++ )) + do + + if [[ ${newInput} == ${history[histArray]}[${i}] ]] + then + hasOccurred=1 + fi + + done + + history[histArray][history[histIndex]]=${newInput} + history[histIndex]=(${history[histIndex]} + 1) % (${histDepth}) + fi + + return ${hasOccurred} +} + +conjugateStrings() { + sentence=$1 + key=$2 + keyPos=$3 + flexions=$4 +# TODO: Check and revise the syntax of all expressions! + + result=" " + copy(${sentence}, ${keyPos} + length(${key}), length(${sentence})) + " " + + for pair in ${flexions[@]} + do + left="" + right=${result} + position=$(pos $(${pair[0]}) "${right}") + + while (( ${position} > 0 )) + do + left=$(( ${left} + copy(${right}, 1, ${position}-1) + ${pair[1]} )) + right=$(copy "${right}" $(( ${position} + length(${pair[0]}) )) $(length "${right}")) + position=$(pos $(${pair[0]}) "${right}") + done + + result=$(( ${left} + ${right} )) + done + + # Eliminate multiple spaces + position=$(pos $(" ") "${result}") + + while (( ${position} > 0 )) + do + result=$(( copy(${result}, 1, ${position}-1) + copy(${result}, ${position}+1, length(${result})) )) + position=$(pos $(" ") "${result}") + done + +} + +# Looks for the occurrence of the first of the strings +# contained in keywords within the given sentence (in +# array order). +# Returns an array of +# 0: the index of the first identified keyword (if any, otherwise -1), +# 1: the position inside sentence (0 if not found) +findKeyword() { + keyMap=$1 + sentence=$2 +# TODO: Check and revise the syntax of all expressions! + + # Contains the index of the keyword and its position in sentence + set -A result=($(( -1 )) $(0)) + i=0 + + while [[ (${result[0]} < 0) && (${i} < length(${keyMap})) ]] + do + entry=${keyMap[${i}]} + position=$(pos $(${entry[keyword]}) "${sentence}") + + if (( ${position} > 0 )) + then + result[0]=${i} + result[1]=${position} + fi + + i=$(( ${i}+1 )) + done + +} + +# Converts the sentence to lowercase, eliminates all +# interpunction (i.e. ',', '.', ';'), and pads the +# sentence among blanks +normalizeInput() { + sentence=$1 +# TODO: Check and revise the syntax of all expressions! + + sentence=$(lowercase "${sentence}") + + for symbol in '.' ',' ';' '!' '?' + do + position=$(pos "${symbol}" "${sentence}") + + while (( ${position} > 0 )) + do + sentence=$(( copy(${sentence}, 1, ${position}-1) + copy(${sentence}, ${position}+1, length(${sentence})) )) + position=$(pos "${symbol}" "${sentence}") + done + + done + + result=" " + ${sentence} + " " +} + +setupGoodByePhrases() { +# TODO: Check and revise the syntax of all expressions! + + set -A phrases[0]=($(" shut") $("Okay. If you feel that way I\'ll shut up. ... Your choice.")) + set -A phrases[1]=($("bye") $("Well, let\'s end our talk for now. See you later. Bye.")) + return ${phrases} +} + +# The lower the index the higher the rank of the keyword (search is sequential). +# The index of the first keyword found in a user sentence maps to a respective +# reply ring as defined in `setupReplies()´. +setupKeywords() { +# TODO: Check and revise the syntax of all expressions! + + # The empty key string (last entry) is the default clause - will always be found + set -A keywords[39]=([keyword]="" [index]=29) + set -A keywords[0]=([keyword]="can you " [index]=0) + set -A keywords[1]=([keyword]="can i " [index]=1) + set -A keywords[2]=([keyword]="you are " [index]=2) + set -A keywords[3]=([keyword]="you\'re " [index]=2) + set -A keywords[4]=([keyword]="i don't " [index]=3) + set -A keywords[5]=([keyword]="i feel " [index]=4) + set -A keywords[6]=([keyword]="why don\'t you " [index]=5) + set -A keywords[7]=([keyword]="why can\'t i " [index]=6) + set -A keywords[8]=([keyword]="are you " [index]=7) + set -A keywords[9]=([keyword]="i can\'t " [index]=8) + set -A keywords[10]=([keyword]="i am " [index]=9) + set -A keywords[11]=([keyword]="i\'m " [index]=9) + set -A keywords[12]=([keyword]="you " [index]=10) + set -A keywords[13]=([keyword]="i want " [index]=11) + set -A keywords[14]=([keyword]="what " [index]=12) + set -A keywords[15]=([keyword]="how " [index]=12) + set -A keywords[16]=([keyword]="who " [index]=12) + set -A keywords[17]=([keyword]="where " [index]=12) + set -A keywords[18]=([keyword]="when " [index]=12) + set -A keywords[19]=([keyword]="why " [index]=12) + set -A keywords[20]=([keyword]="name " [index]=13) + set -A keywords[21]=([keyword]="cause " [index]=14) + set -A keywords[22]=([keyword]="sorry " [index]=15) + set -A keywords[23]=([keyword]="dream " [index]=16) + set -A keywords[24]=([keyword]="hello " [index]=17) + set -A keywords[25]=([keyword]="hi " [index]=17) + set -A keywords[26]=([keyword]="maybe " [index]=18) + set -A keywords[27]=([keyword]=" no" [index]=19) + set -A keywords[28]=([keyword]="your " [index]=20) + set -A keywords[29]=([keyword]="always " [index]=21) + set -A keywords[30]=([keyword]="think " [index]=22) + set -A keywords[31]=([keyword]="alike " [index]=23) + set -A keywords[32]=([keyword]="yes " [index]=24) + set -A keywords[33]=([keyword]="friend " [index]=25) + set -A keywords[34]=([keyword]="computer" [index]=26) + set -A keywords[35]=([keyword]="bot " [index]=26) + set -A keywords[36]=([keyword]="smartphone" [index]=27) + set -A keywords[37]=([keyword]="father " [index]=28) + set -A keywords[38]=([keyword]="mother " [index]=28) + return ${keywords} +} + +# Returns an array of pairs of mutualy substitutable +setupReflexions() { +# TODO: Check and revise the syntax of all expressions! + + set -A reflexions[0]=($(" are ") $(" am ")) + set -A reflexions[1]=($(" were ") $(" was ")) + set -A reflexions[2]=($(" you ") $(" I ")) + set -A reflexions[3]=($(" your") $(" my")) + set -A reflexions[4]=($(" i\'ve ") $(" you\'ve ")) + set -A reflexions[5]=($(" i\'m ") $(" you\'re ")) + set -A reflexions[6]=($(" me ") $(" you ")) + set -A reflexions[7]=($(" my ") $(" your ")) + set -A reflexions[8]=($(" i ") $(" you ")) + set -A reflexions[9]=($(" am ") $(" are ")) + return ${reflexions} +} + +# This routine sets up the reply rings addressed by the key words defined in +# routine `setupKeywords()´ and mapped hitherto by the cross table defined +# in `setupMapping()´ +setupReplies() { +# TODO: Check and revise the syntax of all expressions! + + # We start with the highest index for performance reasons + # (is to avoid frequent array resizing) + set -A replies[29]=($("Say, do you have any psychological problems?") $("What does that suggest to you?") $("I see.") $("I'm not sure I understand you fully.") $("Come come elucidate your thoughts.") $("Can you elaborate on that?") $("That is quite interesting.")) + set -A replies[0]=($("Don't you believe that I can*?") $("Perhaps you would like to be like me?") $("You want me to be able to*?")) + set -A replies[1]=($("Perhaps you don't want to*?") $("Do you want to be able to*?")) + set -A replies[2]=($("What makes you think I am*?") $("Does it please you to believe I am*?") $("Perhaps you would like to be*?") $("Do you sometimes wish you were*?")) + set -A replies[3]=($("Don't you really*?") $("Why don't you*?") $("Do you wish to be able to*?") $("Does that trouble you*?")) + set -A replies[4]=($("Do you often feel*?") $("Are you afraid of feeling*?") $("Do you enjoy feeling*?")) + set -A replies[5]=($("Do you really believe I don't*?") $("Perhaps in good time I will*.") $("Do you want me to*?")) + set -A replies[6]=($("Do you think you should be able to*?") $("Why can't you*?")) + set -A replies[7]=($("Why are you interested in whether or not I am*?") $("Would you prefer if I were not*?") $("Perhaps in your fantasies I am*?")) + set -A replies[8]=($("How do you know you can't*?") $("Have you tried?") $("Perhaps you can now*.")) + set -A replies[9]=($("Did you come to me because you are*?") $("How long have you been*?") $("Do you believe it is normal to be*?") $("Do you enjoy being*?")) + set -A replies[10]=($("We were discussing you--not me.") $("Oh, I*.") $("You're not really talking about me, are you?")) + set -A replies[11]=($("What would it mean to you if you got*?") $("Why do you want*?") $("Suppose you soon got*...") $("What if you never got*?") $("I sometimes also want*.")) + set -A replies[12]=($("Why do you ask?") $("Does that question interest you?") $("What answer would please you the most?") $("What do you think?") $("Are such questions on your mind often?") $("What is it that you really want to know?") $("Have you asked anyone else?") $("Have you asked such questions before?") $("What else comes to mind when you ask that?")) + set -A replies[13]=($("Names don't interest me.") $("I don't care about names -- please go on.")) + set -A replies[14]=($("Is that the real reason?") $("Don't any other reasons come to mind?") $("Does that reason explain anything else?") $("What other reasons might there be?")) + set -A replies[15]=($("Please don't apologize!") $("Apologies are not necessary.") $("What feelings do you have when you apologize?") $("Don't be so defensive!")) + set -A replies[16]=($("What does that dream suggest to you?") $("Do you dream often?") $("What persons appear in your dreams?") $("Are you disturbed by your dreams?")) + set -A replies[17]=($("How do you do ...please state your problem.")) + set -A replies[18]=($("You don't seem quite certain.") $("Why the uncertain tone?") $("Can't you be more positive?") $("You aren't sure?") $("Don't you know?")) + set -A replies[19]=($("Are you saying no just to be negative?") $("You are being a bit negative.") $("Why not?") $("Are you sure?") $("Why no?")) + set -A replies[20]=($("Why are you concerned about my*?") $("What about your own*?")) + set -A replies[21]=($("Can you think of a specific example?") $("When?") $("What are you thinking of?") $("Really, always?")) + set -A replies[22]=($("Do you really think so?") $("But you are not sure you*?") $("Do you doubt you*?")) + set -A replies[23]=($("In what way?") $("What resemblance do you see?") $("What does the similarity suggest to you?") $("What other connections do you see?") $("Could there really be some connection?") $("How?") $("You seem quite positive.")) + set -A replies[24]=($("Are you sure?") $("I see.") $("I understand.")) + set -A replies[25]=($("Why do you bring up the topic of friends?") $("Do your friends worry you?") $("Do your friends pick on you?") $("Are you sure you have any friends?") $("Do you impose on your friends?") $("Perhaps your love for friends worries you.")) + set -A replies[26]=($("Do computers worry you?") $("Are you talking about me in particular?") $("Are you frightened by machines?") $("Why do you mention computers?") $("What do you think machines have to do with your problem?") $("Don't you think computers can help people?") $("What is it about machines that worries you?")) + set -A replies[27]=($("Do you sometimes feel uneasy without a smartphone?") $("Have you had these phantasies before?") $("Does the world seem more real for you via apps?")) + set -A replies[28]=($("Tell me more about your family.") $("Who else in your family*?") $("What does family relations mean for you?") $("Come on, How old are you?")) + setupReplies=${replies} +} + +# Concept and lisp implementation published by Joseph Weizenbaum (MIT): +# "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" - In: +# Computational Linguistis 1(1966)9, pp. 36-45 +# Revision history: +# 2016-10-06 Initial version +# 2017-03-29 Two diagrams updated (comments translated to English) +# 2017-03-29 More keywords and replies added +# 2019-03-14 Replies and mapping reorganised for easier maintenance +# 2019-03-15 key map joined from keyword array and index map +# 2019-03-28 Keyword "bot" inserted (same reply ring as "computer") +# 2019-11-28 New global type "History" (to ensure a homogenous array) +# TODO: Check and revise the syntax of all expressions! + +# Title information +echo "************* ELIZA **************" +echo "* Original design by J. Weizenbaum" +echo "**********************************" +echo "* Adapted for Basic on IBM PC by" +echo "* - Patricia Danielson" +echo "* - Paul Hashfield" +echo "**********************************" +echo "* Adapted for Structorizer by" +echo "* - Kay Gürtzig / FH Erfurt 2016" +echo "* Version: 2.3 (2019-11-28)" +echo "* (Requires at least Structorizer 3.30-03 to run)" +echo "**********************************" +# Stores the last five inputs of the user in a ring buffer, +# the second component is the rolling (over-)write index. +set -A history=([histArray]={"", "", "", "", ""} [histIndex]=0) +replies=setupReplies +reflexions=setupReflexions +byePhrases=setupGoodByePhrases +keyMap=setupKeywords +offsets[length(${keyMap})-1]=0 +isGone=0 +# Starter +echo "Hi! I\'m your new therapist. My name is Eliza. What\'s your problem?" + +# NOTE: This is an automatically inserted copy of the loop body below. +read userInput +# Converts the input to lowercase, cuts out interpunctation +# and pads the string +userInput=normalizeInput "${userInput}" +isGone=checkGoodBye "${userInput}" "${byePhrases}" + +if [[ ! ${isGone} ]] +then + reply="Please don\'t repeat yourself!" + isRepeated=checkRepetition "${history}" "${userInput}" + + if [[ ! ${isRepeated} ]] + then + findInfo=findKeyword "${keyMap}" "${userInput}" + keyIndex=${findInfo[0]} + + if [[ ${keyIndex} < 0 ]] + then + # Should never happen... + keyIndex=$(( length(${keyMap})-1 )) + fi + + entry=${keyMap[${keyIndex}]} + # Variable part of the reply + varPart="" + + if [[ length(${entry[keyword]}) > 0 ]] + then + varPart=conjugateStrings "${userInput}" $(${entry[keyword]}) $(${findInfo[1]}) "${reflexions}" + fi + + replyRing=${replies[${entry[index]}]} + reply=${replyRing[${offsets[${keyIndex}]}]} + offsets[${keyIndex}]=(${offsets[${keyIndex}]} + 1) % length(${replyRing}) + posAster=$(pos $("*") "${reply}") + + if (( ${posAster} > 0 )) + then + + if [[ ${varPart} == " " ]] + then + reply="You will have to elaborate more for me to help you." + + else + delete "${reply}" "${posAster}" $(1) + insert "${varPart}" "${reply}" "${posAster}" + fi + + fi + + reply=adjustSpelling "${reply}" + fi + + echo ${reply} +fi + +while [[ ${isGone} ]] +do + read userInput + # Converts the input to lowercase, cuts out interpunctation + # and pads the string + userInput=normalizeInput "${userInput}" + isGone=checkGoodBye "${userInput}" "${byePhrases}" + + if [[ ! ${isGone} ]] + then + reply="Please don\'t repeat yourself!" + isRepeated=checkRepetition "${history}" "${userInput}" + + if [[ ! ${isRepeated} ]] + then + findInfo=findKeyword "${keyMap}" "${userInput}" + keyIndex=${findInfo[0]} + + if [[ ${keyIndex} < 0 ]] + then + # Should never happen... + keyIndex=$(( length(${keyMap})-1 )) + fi + + entry=${keyMap[${keyIndex}]} + # Variable part of the reply + varPart="" + + if [[ length(${entry[keyword]}) > 0 ]] + then + varPart=conjugateStrings "${userInput}" $(${entry[keyword]}) $(${findInfo[1]}) "${reflexions}" + fi + + replyRing=${replies[${entry[index]}]} + reply=${replyRing[${offsets[${keyIndex}]}]} + offsets[${keyIndex}]=(${offsets[${keyIndex}]} + 1) % length(${replyRing}) + posAster=$(pos $("*") "${reply}") + + if (( ${posAster} > 0 )) + then + + if [[ ${varPart} == " " ]] + then + reply="You will have to elaborate more for me to help you." + + else + delete "${reply}" "${posAster}" $(1) + insert "${varPart}" "${reply}" "${posAster}" + fi + + fi + + reply=adjustSpelling "${reply}" + fi + + echo ${reply} + fi + +done + diff --git a/samples/export/ksh/SORTING_TEST_MAIN.ksh b/samples/export/ksh/SORTING_TEST_MAIN.ksh index 473a80af..7f08f8ea 100644 --- a/samples/export/ksh/SORTING_TEST_MAIN.ksh +++ b/samples/export/ksh/SORTING_TEST_MAIN.ksh @@ -1,5 +1,5 @@ #!/usr/bin/ksh -# Generated by Structorizer 3.30-02 +# Generated by Structorizer 3.30-03 # # Copyright (C) 2019-10-02 Kay Gürtzig # License: GPLv3-link @@ -92,7 +92,7 @@ maxHeapify() { temp=${heap[${i}]} heap[${i}]=${heap[${max}]} heap[${max}]=${temp} - maxHeapify $(${heap}) $(${max}) $(${range}) + maxHeapify "${heap}" "${max}" "${range}" fi } @@ -180,11 +180,11 @@ buildMaxHeap() { heap=$1 # TODO: Check and revise the syntax of all expressions! - lgth=$(length $(${heap})) + lgth=$(length "${heap}") for (( k=(( ${lgth} / 2 - 1 )); k>=0; k-- )) do - maxHeapify $(${heap}) $(${k}) $(${lgth}) + maxHeapify "${heap}" "${k}" "${lgth}" done } @@ -206,23 +206,23 @@ quickSort() { p=$(( random(${stop}-${start}) + ${start} )) # Partition the array into smaller and greater elements # Get the resulting (and final) position of the pivot element - p=$(partition $(${values}) $(${start}) $(${stop}) $(${p})) + p=partition "${values}" "${start}" "${stop}" "${p}" # Sort subsequances separately and independently ... # ========================================================== # ================= START PARALLEL SECTION ================= # ========================================================== - pids3dfab37d="" + pids7fed1521="" ( # Sort left (lower) array part - quickSort $(${values}) $(${start}) $(${p}) + quickSort "${values}" "${start}" "${p}" ) & - pids3dfab37d="${pids3dfab37d} $!" + pids7fed1521="${pids7fed1521} $!" ( # Sort right (higher) array part - quickSort $(${values}) $(( ${p}+1 )) $(${stop}) + quickSort "${values}" $(( ${p}+1 )) "${stop}" ) & - pids3dfab37d="${pids3dfab37d} $!" - wait ${pids3dfab37d} + pids7fed1521="${pids7fed1521} $!" + wait ${pids7fed1521} # ========================================================== # ================== END PARALLEL SECTION ================== # ========================================================== @@ -236,8 +236,8 @@ heapSort() { values=$1 # TODO: Check and revise the syntax of all expressions! - buildMaxHeap $(${values}) - heapRange=$(length $(${values})) + buildMaxHeap "${values}" + heapRange=$(length "${values}") for (( k=(( ${heapRange} - 1 )); k>=1; k-- )) do @@ -246,7 +246,7 @@ heapSort() { maximum=${values[0]} values[0]=${values[${heapRange}]} values[${heapRange}]=${maximum} - maxHeapify $(${values}) $(0) $(${heapRange}) + maxHeapify "${values}" $(0) "${heapRange}" done } @@ -291,7 +291,7 @@ do done -# Kopiere das Array für exakte Vergleichbarkeit +# Copy the array for exact comparability for (( i=0; i<=(( ${elementCount}-1 )); i++ )) do values2[${i}]=${values1[${i}]} @@ -301,26 +301,26 @@ done # ========================================================== # ================= START PARALLEL SECTION ================= # ========================================================== -pids4f085546="" +pids247e34b9="" ( - bubbleSort $(${values1}) + bubbleSort "${values1}" ) & -pids4f085546="${pids4f085546} $!" +pids247e34b9="${pids247e34b9} $!" ( - quickSort $(${values2}) $(0) $(${elementCount}) + quickSort "${values2}" $(0) "${elementCount}" ) & -pids4f085546="${pids4f085546} $!" +pids247e34b9="${pids247e34b9} $!" ( - heapSort $(${values3}) + heapSort "${values3}" ) & -pids4f085546="${pids4f085546} $!" -wait ${pids4f085546} +pids247e34b9="${pids247e34b9} $!" +wait ${pids247e34b9} # ========================================================== # ================== END PARALLEL SECTION ================== # ========================================================== -ok1=$(testSorted $(${values1})) -ok2=$(testSorted $(${values2})) -ok3=$(testSorted $(${values3})) +ok1=testSorted "${values1}" +ok2=testSorted "${values2}" +ok3=testSorted "${values3}" if [[ ! ${ok1} || ! ${ok2} || ! ${ok3} ]] then diff --git a/samples/export/ksh/TextDemo.ksh b/samples/export/ksh/TextDemo.ksh new file mode 100644 index 00000000..3791409c --- /dev/null +++ b/samples/export/ksh/TextDemo.ksh @@ -0,0 +1,1219 @@ +#!/usr/bin/ksh +# Generated by Structorizer 3.30-03 +# +# Copyright (C) 2019-10-10 Kay Gürtzig +# License: GPLv3-link +# GNU General Public License (V 3) +# https://www.gnu.org/licenses/gpl.html +# http://www.gnu.de/documents/gpl.de.html +# + +# Draws a blank for font height h, ignoring the colorNo +blank() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + penUp + right $(90) + forward "${width}" # color = ffffff + left $(90) +} + +forward() { + len=$1 + color=$2 +# TODO: Check and revise the syntax of all expressions! + + case ${color} in + + 1) + forward "${len}" # color = ffffff + ;; + + 2) + forward "${len}" # color = ff8080 + ;; + + 3) + forward "${len}" # color = ffff80 + ;; + + 4) + forward "${len}" # color = 80ff80 + ;; + + 5) + forward "${len}" # color = 80ffff + ;; + + 6) + forward "${len}" # color = 0080ff + ;; + + 7) + forward "${len}" # color = ff80c0 + ;; + + 8) + forward "${len}" # color = c0c0c0 + ;; + + 9) + forward "${len}" # color = ff8000 + ;; + + 10) + forward "${len}" # color = 8080ff + ;; + esac + +} + +# Draws letter A in colour specified by colorNo with font height h +# from the current turtle position. +letterA() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${h}*${h} + ${width}*${width}/4.0 ))) + rotAngle=$(toDegrees $(atan $(( ${width}/2.0/${h} )))) + right "${rotAngle}" + forward $(( ${hypo}/2.0 )) "${colorNo}" + right $(( 90 - ${rotAngle} )) + forward $(( ${width}/2.0 )) "${colorNo}" + penUp + backward $(( ${width}/2.0 )) # color = ffffff + penDown + left $(( 90 - ${rotAngle} )) + forward $(( ${hypo}/2.0 )) "${colorNo}" + left $(( 2*${rotAngle} )) + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" +} + +# Draws letter E in colour specified by colorNo with font height h +# from the current turtle position. +letterE() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + right $(90) + forward "${width}" "${colorNo}" + right $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + left $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) +} + +# Draws letter F in colour specified by colorNo with font height h +# from the current turtle position. +letterF() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + right $(90) + forward "${width}" "${colorNo}" + right $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) + penUp + forward $(( ${h}/2.0 )) # color = ffffff + left $(90) + forward "${width}" # color = ffffff + penDown + left $(90) +} + +# Draws letter H in colour specified by colorNo with font height h +# from the current turtle position. +letterH() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + penUp + right $(90) + forward "${width}" # color = ffffff + right $(90) + penDown + forward $(( ${h}/2.0 )) "${colorNo}" + right $(90) + forward "${width}" "${colorNo}" + penUp + backward "${width}" # color = ffffff + left $(90) + penDown + forward $(( ${h}/2.0 )) "${colorNo}" + left $(180) +} + +# Draws letter I in colour specified by colorNo with font height h +# from the current turtle position. +letterI() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( ${b} / sqrt(2.0) )) + penUp + right $(90) + forward "${c}" # color = ffffff + penDown + forward "${b}" "${colorNo}" + penUp + backward $(( ${b}/2.0 )) # color = ffffff + left $(90) + penDown + forward "${h}" "${colorNo}" + penUp + right $(90) + backward $(( ${b}/2.0 )) # color = ffffff + penDown + forward "${b}" "${colorNo}" + penUp + forward $(( ${b}/2 + ${c} )) # color = ffffff + left $(90) + backward "${h}" # color = ffffff + penDown +} + +# Draws letter K in colour specified by colorNo with font height h +# from the current turtle position. +letterK() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + diag=$(( ${h}/sqrt(2.0) )) + forward "${h}" "${colorNo}" + penUp + right $(90) + forward "${width}" # color = ffffff + right $(135) + penDown + forward "${diag}" "${colorNo}" + left $(90) + forward "${diag}" "${colorNo}" + left $(135) +} + +# Draws letter L in colour specified by colorNo with font height h +# from the current turtle position. +letterL() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + forward "${h}" "${colorNo}" + penUp + backward "${h}" # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(90) +} + +# Draws letter M in colour specified by colorNo with font height h +# from the current turtle position. +letterM() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(( sqrt(${width}*${width} + ${h}*${h})/2.0 )) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + forward "${h}" "${colorNo}" + left "${rotAngle}" + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + left "${rotAngle}" + forward $(( -${h} )) "${colorNo}" +} + +# Draws letter N in colour specified by colorNo with font height h +# from the current turtle position. +letterN() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${width}*${width} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + forward "${h}" "${colorNo}" + left "${rotAngle}" + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" + forward "${h}" "${colorNo}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws letter T in colour specified by colorNo with font height h +# from the current turtle position. +letterT() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + penUp + forward "${h}" # color = ffffff + penDown + right $(90) + forward "${width}" "${colorNo}" + penUp + backward $(( ${width}/2.0 )) # color = ffffff + penDown + right $(90) + forward "${h}" "${colorNo}" + left $(90) + penUp + forward $(( ${width}/2.0 )) # color = ffffff + penDown + left $(90) +} + +# Draws letter V in colour specified by colorNo with font height h +# from the current turtle position. +letterV() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${h}*${h} + ${width}*${width}/4.0 ))) + rotAngle=$(toDegrees $(atan $(( ${width}/2.0/${h} )))) + penUp + forward "${h}" # color = ffffff + left "${rotAngle}" + penDown + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + left "${rotAngle}" + backward "${h}" # color = ffffff + penDown +} + +# Draws letter W in colour specified by colorNo with font height h +# from the current turtle position. +letterW() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + width_3=$(( ${width}/3.0 )) + hypo=$(sqrt $(( ${width_3}*${width_3} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width_3}/${h} )))) + penUp + forward "${h}" # color = ffffff + left "${rotAngle}" + penDown + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + left $(( 90+${rotAngle} )) + forward "${width_3}" # color = ffffff + right $(( 90-${rotAngle} )) + penDown + forward $(( -${hypo} )) "${colorNo}" + right $(( 2*${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + left "${rotAngle}" + backward "${h}" # color = ffffff + penDown +} + +# Draws letter X in colour specified by colorNo with font height h +# from the current turtle position. +letterX() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${width}*${width} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + right "${rotAngle}" + forward "${hypo}" "${colorNo}" + penUp + left $(( 90+${rotAngle} )) + forward "${width}" # color = ffffff + right $(( 90-${rotAngle} )) + penDown + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" +} + +# Draws letter Y in colour specified by colorNo with font height h +# from the current turtle position. +letterY() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(( sqrt(${width}*${width} + ${h}*${h})/2.0 )) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + penUp + forward "${h}" # color = ffffff + left "${rotAngle}" + penDown + forward $(( -${hypo} )) "${colorNo}" + right "${rotAngle}" + penUp + backward $(( ${h}/2.0 )) # color = ffffff + penDown + forward $(( ${h}/2.0 )) "${colorNo}" + right "${rotAngle}" + forward "${hypo}" "${colorNo}" + left "${rotAngle}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws letter Z in colour specified by colorNo with font height h +# from the current turtle position. +letterZ() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h}/2.0 )) + hypo=$(sqrt $(( ${width}*${width} + ${h}*${h} ))) + rotAngle=$(toDegrees $(atan $(( ${width}/${h} )))) + penUp + forward "${h}" # color = ffffff + right $(90) + penDown + forward "${width}" "${colorNo}" + left $(( 90-${rotAngle} )) + forward $(( -${hypo} )) "${colorNo}" + right $(( 90-${rotAngle} )) + forward "${width}" "${colorNo}" + left $(90) +} + +# Draws nEdges edges of a regular n-polygon with edge length a +# counter-clockwise, if ctrclkws is true, or clockwise if ctrclkws is false. +polygonPart() { + a=$1 + n=$2 + ctrclkws=$3 + nEdges=$4 + color=$5 +# TODO: Check and revise the syntax of all expressions! + + rotAngle=$(( 360.0/${n} )) + + if [[ ${ctrclkws} ]] + then + rotAngle=$(( -${rotAngle} )) + fi + + for (( k=1; k<=${nEdges}; k++ )) + do + right "${rotAngle}" + forward "${a}" "${color}" + done + +} + +# Draws a dummy character (small centered square) with font height h and +# the colour encoded by colorNo +charDummy() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + width=$(( ${h} / 2.0 )) + # Octagon edge length (here: edge lengzh of the square) + b=$(( ${width} / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( (${width} - ${b}) / 2.0 )) + d=$(( ${b} / sqrt(2.0) )) + penUp + forward $(( ${h}/2.0-${b}/2.0 )) # color = ffffff + right $(90) + forward "${c}" # color = ffffff + right $(90) + penDown + # Draws the square with edge length b + polygonPart "${b}" $(4) $(1) $(4) "${colorNo}" + penUp + left $(90) + forward $(( ${b} + ${c} )) # color = ffffff + left $(90) + backward $(( ${h}/2.0-${b}/2.0 )) # color = ffffff + penDown +} + +# Draws a comma in colour specified by colorNo with font height h +# from the current turtle position. +comma() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + rotAngle=$(toDegrees $(atan $(0.5))) + hypo=$(( ${c} * sqrt(1.25) )) + penUp + right $(90) + forward $(( (${c}+${b})/2.0 + ${c} )) # color = ffffff + penDown + # Counterclockwise draw 3 edges of a square with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(1) $(3) "${colorNo}" + left $(90) + forward $(( ${c}/2.0 )) "${colorNo}" + right $(90) + forward "${c}" "${colorNo}" + left $(( 180 - ${rotAngle} )) + forward "${hypo}" "${colorNo}" + penUp + right $(( 90 - ${rotAngle} )) + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + penDown +} + +# Draws an exclamation mark in the colour encoded by colorNo with font height h +# from the current turtle position. +exclMk() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + width=$(( ${h}/2.0 )) + length1=$(( ${h} - (${b}+${c})/2.0 )) + length2=$(( ${length1} - 2*${c} )) + hypo=$(sqrt $(( ${width}*${width}/16.0 + ${length2}*${length2} ))) + # 360°/8 + rotAngle=45 + rotAngle2=$(toDegrees $(atan $(( ${width}/4.0/${length2} )))) + penUp + forward "${length1}" # color = ffffff + right $(90) + forward $(( ${width}/2.0 )) # color = ffffff + left $(( 90 + ${rotAngle} )) + penDown + # Clockwise draw 5 edges of an octagon with edge length b/2 + # in the colour endcoded by colorNo + polygonPart $(( ${b}/2.0 )) $(8) $(0) $(5) "${colorNo}" + right "${rotAngle2}" + forward "${hypo}" "${colorNo}" + left $(( 2*${rotAngle2} )) + forward $(( -${hypo} )) "${colorNo}" + penUp + forward "${hypo}" # color = ffffff + right "${rotAngle2}" + forward "${c}" # color = ffffff + left $(90) + forward $(( ${c}/2.0 )) # color = ffffff + penDown + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(0) $(4) "${colorNo}" + penUp + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + backward "${c}" # color = ffffff + penDown +} + +# Draws a full stop in colour specified by colorNo with font height h +# from the current turtle position. +fullSt() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + penUp + right $(90) + forward $(( (${c}+${b})/2.0 + ${c} )) # color = ffffff + penDown + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(1) $(4) "${colorNo}" + penUp + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + penDown +} + +# Draws letter B in colour specified by colorNo with font height h +# from the current turtle position. +letterB() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the outer corner triangle of the octagon + c=$(( ${b} / sqrt(2.0) )) + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + left $(180) + forward $(( ${b} + ${c} )) # color = ffffff + penDown + # Clockwise draw 4 edges of an octagon with edge length b + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + left $(180) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(90) +} + +# Draws letter C in the colour encoded by colorNo with font height h +# from the current turtle position. +letterC() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the outer trinagle at the octagon corner + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Clockwise draws 3 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart "${b}" $(8) $(1) $(3) "${colorNo}" + left "${rotAngle}" + penUp + forward $(( 2*${b} + 2*${c} )) # color = ffffff + penDown + # Counterclockwise draws 4 edges of an octagon with edge length b + # iin the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) "${colorNo}" + penDown + left $(90) +} + +# Draws letter D in colour specified by colorNo with font height h +# from the current turtle position. +letterD() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart "${b}" $(8) $(0) $(2) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + # Clockwise draw 2 edges of an octagon with edge length b in the colour + # encoded by colorNo + polygonPart "${b}" $(8) $(0) $(2) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + left $(180) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(90) +} + +# Draws letter G in colour specified by colorNo with font height h +# from the current turtle position. +letterG() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon. + c=$(( ${b} / sqrt(2.0) )) + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + left $(90) + forward $(( ${b}/2.0 + ${c} )) "${colorNo}" + penUp + backward $(( ${b}/2.0 + ${c} )) # color = ffffff + right $(90) + forward $(( ${b} + ${c} )) # color = ffffff + penDown + # Counterclockwise draw 4 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) "${colorNo}" + penDown + left $(90) +} + +# Draws letter J in colour encoded by colorNo with font height h +# from the current turtle position. +letterJ() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 3 edges of an octagon with edge length b in + # the colour encoded by colorNo + polygonPart "${b}" $(8) $(1) $(3) "${colorNo}" + left "${rotAngle}" + forward $(( ${h} - ${c} )) "${colorNo}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws letter O in colour specified by colorNo with font height h +# from the current turtle position. +letterO() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( ${b} / sqrt(2.0) )) + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(90) +} + +# Draws letter P in colour specified by colorNo with font height h +# from the current turtle position. +letterP() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Octagon edge length + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Cathetus of the corner triangle outside the octagon + c=$(( ${b} / sqrt(2.0) )) + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + penUp + backward $(( ${b} + 2*${c} )) # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) # color = ffffff + penDown + left $(180) +} + +# Draws letter Q in colour specified by colorNo with font height h +# from the current turtle position. +letterQ() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + # Counterclockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(4) "${colorNo}" + forward $(( ${b} + 2*${c} )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${b} + 2*${c} )) # color = ffffff + right "${rotAngle}" + backward "${b}" # color = ffffff + penDown + forward "${b}" "${colorNo}" + left $(( 90 + ${rotAngle} )) +} + +# Zeichnet den Buchstaben R von der Turtleposition aus +# mit Zeilenhöhe h +letterR() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + forward "${h}" "${colorNo}" + right $(90) + forward $(( ${c}+${b} )) "${colorNo}" + # Clockwise draw 4 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(4) "${colorNo}" + forward "${c}" "${colorNo}" + left $(( 90 + ${rotAngle} )) + forward $(( sqrt(2.0)*(${b} + 2*${c}) )) "${colorNo}" + left $(( 90 + ${rotAngle} )) +} + +# Draws letter S in colour specified by colorNo with font height h +# from the current turtle position. +letterS() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + right $(180) + # Counterclockwise draw 6 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(1) $(6) "${colorNo}" + # Clockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(5) "${colorNo}" + right "${rotAngle}" + penUp + forward $(( 2*${b} + 3*${c} )) # color = ffffff + penDown + left $(180) +} + +# Draws letter U in colour specified by colorNo with font height h +# from the current turtle position. +letterU() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # edge length of a regular octagon + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward "${c}" # color = ffffff + penDown + forward $(( ${h} - ${c} )) "${colorNo}" + penUp + backward $(( ${h}-${c} )) # color = ffffff + penDown + right $(180) + # Counterclockwise draw 3 edges of an octagoin with edge length b in colour specified by colorNo + polygonPart "${b}" $(8) $(1) $(3) "${colorNo}" + left "${rotAngle}" + forward $(( ${h} - ${c} )) "${colorNo}" + penUp + backward "${h}" # color = ffffff + penDown +} + +# Draws a question mark in colour specified by colorNo with font height h +# from the current turtle position. +qstnMk() { + h=$1 + colorNo=$2 +# TODO: Check and revise the syntax of all expressions! + + # Achteck-Kantenlänge + b=$(( ${h} * 0.5 / (sqrt(2.0) + 1) )) + # Eckenlänge außen am Achteck + c=$(( ${b} / sqrt(2.0) )) + # 360°/8 + rotAngle=45 + penUp + forward $(( ${h}-${c} )) # color = ffffff + penDown + # Counterclockwise draw 5 edges of an octagon with edge length b + # in the colour endcoded by colorNo + polygonPart "${b}" $(8) $(0) $(5) "${colorNo}" + forward "${c}" "${colorNo}" + left "${rotAngle}" + forward $(( ${b}/2.0 )) "${colorNo}" + penUp + forward "${c}" # color = ffffff + left $(90) + forward $(( ${c}/2.0 )) # color = ffffff + penDown + # Counterclockwise draw all 4 edges of a squarfe with edge length c + # in the colour endcoded by colorNo + polygonPart "${c}" $(4) $(0) $(4) "${colorNo}" + penUp + forward $(( (${c} + ${b})/2.0 )) # color = ffffff + left $(90) + backward "${c}" # color = ffffff + penDown +} + +# Has the turtle draw the given string 'text´ with font height 'h´ (in +# pixels) and the colour coded by integer 'c´ from the current Turtle +# position to the Turtle canvas. If the turtle looks North then +# the text will be written rightwards. In the event, the turtle will be +# placed behind the text in original orientation (such that the next text +# would be written like a continuation. Colour codes: +# 1 = black +# 2 = red +# 3 = yellow +# 4 = green +# 5 = cyan +# 6 = blue +# 7 = pink +# 8 = grey +# 9 = orange +# 10 = violet +# All letters (ASCII) will be converted to uppercase, digits cannot +# be represented, the set of representable special characters is: +# '.', ',', '!', '?'. Other characters will be shown as a small +# centred square (dummy character). +drawText() { + text=$1 + h=$2 + c=$3 +# TODO: Check and revise the syntax of all expressions! + + gap=$(( ${h}/10.0 )) + + for (( k=1; k<=length "${text}"; k++ )) + do + letter=$(uppercase $(copy "${text}" "${k}" $(1))) + + if [[ ${letter} == "," ]] + then + comma "${h}" "${c}" + + else + + # "," cannot be chacked against because the comma is misinterpreted + # as selector list separator. + case ${letter} in + + "A") + letterA "${h}" "${c}" + ;; + + "B") + letterB "${h}" "${c}" + ;; + + "C") + letterC "${h}" "${c}" + ;; + + "D") + letterD "${h}" "${c}" + ;; + + "E") + letterE "${h}" "${c}" + ;; + + "F") + letterF "${h}" "${c}" + ;; + + "G") + letterG "${h}" "${c}" + ;; + + "H") + letterH "${h}" "${c}" + ;; + + "I") + letterI "${h}" "${c}" + ;; + + "J") + letterJ "${h}" "${c}" + ;; + + "K") + letterK "${h}" "${c}" + ;; + + "L") + letterL "${h}" "${c}" + ;; + + "M") + letterM "${h}" "${c}" + ;; + + "N") + letterN "${h}" "${c}" + ;; + + "O") + letterO "${h}" "${c}" + ;; + + "P") + letterP "${h}" "${c}" + ;; + + "Q") + letterQ "${h}" "${c}" + ;; + + "R") + letterR "${h}" "${c}" + ;; + + "S") + letterS "${h}" "${c}" + ;; + + "T") + letterT "${h}" "${c}" + ;; + + "U") + letterU "${h}" "${c}" + ;; + + "V") + letterV "${h}" "${c}" + ;; + + "W") + letterW "${h}" "${c}" + ;; + + "X") + letterX "${h}" "${c}" + ;; + + "Y") + letterY "${h}" "${c}" + ;; + + "Z") + letterZ "${h}" "${c}" + ;; + + " ") + blank "${h}" "${c}" + ;; + + "!") + exclMk "${h}" "${c}" + ;; + + "?") + qstnMk "${h}" "${c}" + ;; + + ".") + fullSt "${h}" "${c}" + ;; + + *) + charDummy "${h}" "${c}" + ;; + esac + + fi + + right $(90) + penUp + forward "${gap}" # color = ffffff + penDown + left $(90) + done + +} + +# Demo program for routine drawText() +# Asks the user to enter a text, a wanted text height and colour, +# and then draws this string onto the turtle screen. Places every +# entered text to a new line. +# TODO: Check and revise the syntax of all expressions! + +echo "This is a demo program for text writing with Turleizer." +showTurtle +penDown +y=0 + +# NOTE: This is an automatically inserted copy of the loop body below. +echo -n "Enter some text (empty string to exit)" ; read text +# Make sure the content is interpreted as string +text=$(( "" + ${text} )) + +if [[ ${text} != "" ]] +then + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Height of the text (pixels)" ; read height + while [[ ${height} >= 5 ]] + do + echo -n "Height of the text (pixels)" ; read height + done + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + while [[ ${colour} >= 1 && ${colour} <= 10 ]] + do + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + done + + y=$(( ${y} + ${height} + 2 )) + gotoXY $(0) $(( ${y} - 2 )) + drawText "${text}" "${height}" "${colour}" +fi + +while [[ ${text} == "" ]] +do + echo -n "Enter some text (empty string to exit)" ; read text + # Make sure the content is interpreted as string + text=$(( "" + ${text} )) + + if [[ ${text} != "" ]] + then + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Height of the text (pixels)" ; read height + while [[ ${height} >= 5 ]] + do + echo -n "Height of the text (pixels)" ; read height + done + + # NOTE: This is an automatically inserted copy of the loop body below. + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + while [[ ${colour} >= 1 && ${colour} <= 10 ]] + do + echo -n "Colour (1=black, 2=red, 3=yellow, 4=green, 5=cyan, 6=blue, 7=pink, 8=gray, 9=orange, 10=violet)" ; read colour + done + + y=$(( ${y} + ${height} + 2 )) + gotoXY $(0) $(( ${y} - 2 )) + drawText "${text}" "${height}" "${colour}" + fi + +done + +gotoXY $(0) $(( ${y} + 15 )) +drawText $("Thank you, bye.") $(10) $(4) +hideTurtle diff --git a/src/lu/fisch/structorizer/arranger/Surface.java b/src/lu/fisch/structorizer/arranger/Surface.java index 33bb32ea..f6255c33 100644 --- a/src/lu/fisch/structorizer/arranger/Surface.java +++ b/src/lu/fisch/structorizer/arranger/Surface.java @@ -122,6 +122,7 @@ * Kay Gürtzig 2019-10-13 Bugfix #763: Handling of stale file connections on saving and loading arrangements * Kay Gürtzig 2019-10-14 Bugfix #764: Updating the .arr file of a modified group used to fail. * Kay Gürtzig 2019-10-15 Bugfix #763: On resaving stale diagrams, the shadow path had to be cleared. + * Kay Gürtzig 2019-11-28 Bugfix #788: Offered arrz extraction to user-chosen folder was ignored * ****************************************************************************************************** * @@ -1913,7 +1914,10 @@ private File unzipArrangement(File arrzFile, File targetDir) // } // return arrFile; Archivar archivar = new Archivar(); - ArchiveIndex archiveIndex = archivar.unzipArrangementArchive(arrzFile, null); + // START KGU#775 2019-11-29: Bugfix #788 - the extraction target dir was ignored + //ArchiveIndex archiveIndex = archivar.unzipArrangementArchive(arrzFile, null); + ArchiveIndex archiveIndex = archivar.unzipArrangementArchive(arrzFile, targetDir); + // END KGU#775 2019-11-29 return archiveIndex.arrFile; } diff --git a/src/lu/fisch/structorizer/elements/Element.java b/src/lu/fisch/structorizer/elements/Element.java index 19b67790..0a0848c6 100644 --- a/src/lu/fisch/structorizer/elements/Element.java +++ b/src/lu/fisch/structorizer/elements/Element.java @@ -107,6 +107,9 @@ * Kay Gürtzig 2019-03-29 Issue #718: Breakthrough in drawing speed with syntax highlighting * Kay Gürtzig 2019-05-15 Issue #724: Workaround for diagram titles in writeOutVariables * Kay Gürtzig 2019-08-02 Issue #733: New method getPreferenceKeys() for partial preference export + * Kay Gürtzig 2019-11-17 Issue #739: Support for enum type definitions, addToTypeMap simplified + * Kay Gürtzig 2019-11-24 Bugfix #783 workaround for missing record type info + * Kay Gürtzig 2019-12-02 KGU#782: identifyExprType now also tries to detect char type * ****************************************************************************************************** * @@ -260,7 +263,7 @@ public String toString() public static final String E_HOME_PAGE = "https://structorizer.fisch.lu"; public static final String E_HELP_PAGE = "https://help.structorizer.fisch.lu/index.php"; // END KGU#563 2018-007-26 - public static final String E_VERSION = "3.30-02"; + public static final String E_VERSION = "3.30-03"; public static final String E_THANKS = "Developed and maintained by\n"+ " - Robert Fisch \n"+ @@ -3048,7 +3051,8 @@ else if (stoppers.contains(token)) { /** * Extracts the parameter or component declarations from the parameter list (or * record type definition, respectively) given by {@code declText} and adds their names - * and type descriptions to the respective StringList {@code declNames} and {@code declTypes}. + * and type descriptions to the respective StringList {@code declNames} and {@code declTypes}.
+ * CAUTION: Some elements of {@code declTypes} may be null on return! * @param declText - the text of the declaration inside the parentheses or braces * @param declNames - the names of the declared parameters or record components (in order of occurrence), or null * @param declTypes - the types of the declared parameters or record components (in order of occurrence), or null @@ -3215,12 +3219,16 @@ else if (tokens.get(0).equals("const")) { * If {@code _typeInfo} is given and either {@code typename} was omitted or matches * name of {@code _typeInfo} then unprefixed component values will be associated * to the component names of the type in order of occurrence unless an explicit - * component name prefix occurs. + * component name prefix occurs.
+ * If {@code _typeInfo} is null and {@code generateDummyCompNames} is true then generic + * component names of form {@code "FIXME__"} may be provided for components + * with missing names in the {@code _text}. * @param _text - the initializer expression with or without typename but with braces. * @param _typeInfo - the type map entry for the corresponding record type if available + * @param _generateDummyCompNames - if true then missing component names (not retrievable) will be replaced by generic ones * @return the component map (or null if there are no braces). */ - public static HashMap splitRecordInitializer(String _text, TypeMapEntry _typeInfo) + public static HashMap splitRecordInitializer(String _text, TypeMapEntry _typeInfo, boolean _generateDummyCompNames) { // START KGU#526 2018-08-01: Enh. #423 - effort to make the component order more stable (at higher costs, though) //HashMap components = new HashMap(); @@ -3269,6 +3277,11 @@ else if (guessComponents && i < compNames.length) { components.put(compNames[i], parts.get(i)); } // END KGU#559 2018-07-20 + // START KGU#711 2019-11-24: Bugfix #783 workaround for missing type info + else if (compNames == null && !typename.isEmpty()) { + components.put("FIXME_" + typename + "_" + i, parts.get(i)); + } + // END KGU#711 2019-11-24 } return components; } @@ -3312,6 +3325,11 @@ public static String identifyExprType(HashMap typeMap, Str else if (Function.isFunction(expr)) { typeSpec = (new Function(expr).getResultType("")); } + // START KGU#782 2019-12-02 For certain purposes, e.g. export of FOR-IN loops char detection may be essential + else if (expr.startsWith("'") && expr.endsWith("'") && (expr.length() == 3 || expr.length() == 4 && expr.charAt(1) == '\\')) { + typeSpec = "char"; + } + // END KGU#782 2019-12-02 else if (STRING_PATTERN.matcher(expr).matches()) { typeSpec = "String"; } @@ -3439,6 +3457,9 @@ private static int writeOutVariables(Canvas _canvas, int _x, int _y, String _tex specialSigns.add("record"); specialSigns.add("struct"); // END KGU#388 2017-09-13 + // START KGU#542 2019-11-17: Enh. #739 "enum" added to type definition keywords + specialSigns.add("enum"); + // END KGU#542 2019-11-17 specialSigns.add("mod"); specialSigns.add("div"); // START KGU#331 2017-01-13: Enh. #333 @@ -4355,9 +4376,8 @@ public void updateTypeMap(HashMap typeMap) * @param lineNo - number of the element text line containing the type description * @param isAssigned - is to indicate whether a value is assigned here * @param explicitly - whether the type association was an explicit declaration or just guessed - * @param isCStyle - additional indication whether the type description a C-like syntax */ - protected void addToTypeMap(HashMap typeMap, String varName, String typeSpec, int lineNo, boolean isAssigned, boolean explicitly, boolean isCStyle) + protected void addToTypeMap(HashMap typeMap, String varName, String typeSpec, int lineNo, boolean isAssigned, boolean explicitly) { if (varName != null && !typeSpec.isEmpty()) { TypeMapEntry entry = typeMap.get(varName); @@ -4372,7 +4392,7 @@ protected void addToTypeMap(HashMap typeMap, String varName } else { // Add a new entry to the type map - typeMap.put(varName, new TypeMapEntry(typeSpec, null, null, this, lineNo, isAssigned, explicitly, isCStyle)); + typeMap.put(varName, new TypeMapEntry(typeSpec, null, null, this, lineNo, isAssigned, explicitly)); } } else if (typeEntry == null || !typeEntry.isRecord()) { @@ -4382,7 +4402,7 @@ else if (typeEntry == null || !typeEntry.isRecord()) { } // END KGU#593 2018-10-05 // add an alternative declaration to the type map entry - entry.addDeclaration(typeSpec, this, lineNo, isAssigned, isCStyle); + entry.addDeclaration(typeSpec, this, lineNo, isAssigned); } } } @@ -4395,10 +4415,8 @@ else if (typeEntry == null || !typeEntry.isRecord()) { * @param typeName - name of the new defined type * @param typeSpec - a type-describing string as found in the definition * @param compNames - list of the component identifiers (strings) - * @param compTypes - list of type-describing strings (a type name or a type construction) + * @param compTypes - list of type-describing strings (a type name or a type construction or null!) * @param lineNo - number of the element text line containing the type description - * @param isAssigned - is to indicate whether a value is assigned here - * @param isCStyle - additional indication whether the type description a C-like syntax * @return true if the {@code typeName} was new and could be placed in the {@code typeMap}. */ protected boolean addRecordTypeToTypeMap(HashMap typeMap, String typeName, String typeSpec, StringList compNames, StringList compTypes, int lineNo) @@ -4427,14 +4445,14 @@ protected boolean addRecordTypeToTypeMap(HashMap typeMap, S } else { // Create a named dummy entry - compEntry = new TypeMapEntry(type, type, typeMap, this, lineNo, false, true, false); + compEntry = new TypeMapEntry(type, type, typeMap, this, lineNo, false, true); } } } // FIXME KGU#687 2019-03-16: Issue #408 - no longer needed? else { // Create an unnamed dummy entry - compEntry = new TypeMapEntry(type, null, null, this, lineNo, false, true, false); + compEntry = new TypeMapEntry(type, null, null, this, lineNo, false, true); } } } diff --git a/src/lu/fisch/structorizer/elements/For.java b/src/lu/fisch/structorizer/elements/For.java index 58a50010..786730b0 100644 --- a/src/lu/fisch/structorizer/elements/For.java +++ b/src/lu/fisch/structorizer/elements/For.java @@ -33,39 +33,40 @@ * * Author Date Description * ------ ---- ----------- - * Bob Fisch 2007.12.07 First Issue - * Bob Fisch 2008.02.06 Modified for DIN / not DIN - * Kay Gürtzig 2015.10.11 Method selectElementByCoord(int,int) replaced by getElementByCoord(int,int,boolean) - * Kay Gürtzig 2015.10.12 Comment drawing centralized and breakpoint mechanism prepared. - * Kay Gürtzig 2015.11.04 New mechanism to split and compose the FOR clause into/from dedicated fields - * Kay Gürtzig 2015.11.14 Bugfixes (#28 = KGU#80 and #31 = KGU#82) in Method copy - * Kay Gürtzig 2015.11.30 Inheritance changed: implements ILoop - * Kay Gürtzig 2015.12.01 Bugfix #39 (=KGU#91) -> getText(false), prepareDraw() optimised - * Kay Gürtzig 2016.01.02 Bugfix #78 (KGU#119): New method equals(Element) - * Kay Gürtzig 2016.01.03 Bugfix #87 (KGU#121): Correction in getElementByCoord(), getIcon() - * Kay Gürtzig 2016.02.27 Bugfix #97 (KGU#136): field rect replaced by rect0 in prepareDraw() - * Kay Gürtzig 2016.03.01 Bugfix #97 (KGU#136): Translation-neutral selection - * Kay Gürtzig 2016.03.06 Enh. #77 (KGU#117): Fields for test coverage tracking added - * Kay Gürtzig 2016.03.12 Enh. #124 (KGU#156): Generalized runtime data visualisation - * Kay Gürtzig 2016.03.20 Enh. #84/#135 (KGU#61): enum type and methods introduced/modified + * Bob Fisch 2007-12-07 First Issue + * Bob Fisch 2008-02-06 Modified for DIN / not DIN + * Kay Gürtzig 2015-10-11 Method selectElementByCoord(int,int) replaced by getElementByCoord(int,int,boolean) + * Kay Gürtzig 2015-10-12 Comment drawing centralized and breakpoint mechanism prepared. + * Kay Gürtzig 2015-11-04 New mechanism to split and compose the FOR clause into/from dedicated fields + * Kay Gürtzig 2015-11-14 Bugfixes (#28 = KGU#80 and #31 = KGU#82) in Method copy + * Kay Gürtzig 2015-11-30 Inheritance changed: implements ILoop + * Kay Gürtzig 2015-12-01 Bugfix #39 (=KGU#91) -> getText(false), prepareDraw() optimised + * Kay Gürtzig 2016-01-02 Bugfix #78 (KGU#119): New method equals(Element) + * Kay Gürtzig 2016-01-03 Bugfix #87 (KGU#121): Correction in getElementByCoord(), getIcon() + * Kay Gürtzig 2016-02-27 Bugfix #97 (KGU#136): field rect replaced by rect0 in prepareDraw() + * Kay Gürtzig 2016-03-01 Bugfix #97 (KGU#136): Translation-neutral selection + * Kay Gürtzig 2016-03-06 Enh. #77 (KGU#117): Fields for test coverage tracking added + * Kay Gürtzig 2016-03-12 Enh. #124 (KGU#156): Generalized runtime data visualisation + * Kay Gürtzig 2016-03-20 Enh. #84/#135 (KGU#61): enum type and methods introduced/modified * to distinguish and handle FOR-IN loops - * Kay Gürtzig 2016.04.24 Issue #169: Method findSelected() introduced, copy() modified (KGU#183) - * Kay Gürtzig 2016.05.02 Bugfix #184: constructor For(String) now supports code import (KGU#192) - * Kay Gürtzig 2016.07.21 KGU#207: Slight performance improvement in getElementByCoord() - * Kay Gürtzig 2016.07.30 Enh. #128: New mode "comments plus text" supported, drawing code delegated - * Kay Gürtzig 2016.09.24 Enh. #250: Adaptations to make the new editor design work - * Kay Gürtzig 2016.09.25 Issue #252: ':=' and '<-' equivalence in consistency check + * Kay Gürtzig 2016-04-24 Issue #169: Method findSelected() introduced, copy() modified (KGU#183) + * Kay Gürtzig 2016-05-02 Bugfix #184: constructor For(String) now supports code import (KGU#192) + * Kay Gürtzig 2016-07-21 KGU#207: Slight performance improvement in getElementByCoord() + * Kay Gürtzig 2016-07-30 Enh. #128: New mode "comments plus text" supported, drawing code delegated + * Kay Gürtzig 2016-09-24 Enh. #250: Adaptations to make the new editor design work + * Kay Gürtzig 2016-09-25 Issue #252: ':=' and '<-' equivalence in consistency check * Enh. #253: CodeParser.keywordMap refactored - * Kay Gürtzig 2016.10.04 Enh. #253: Refactoring configuration revised - * Kay Gürtzig 2017.01.26 Enh. #259: Type retrieval support added (for counting loops) - * Kay Gürtzig 2017.04.14 Enh. #259: Approach to guess FOR-IN loop variable type too - * Kay Gürtzig 2017.04.30 Enh. #354: New structured constructors - * Kay Gürtzig 2017.11.02 Issue #447: Precaution against line-continuating backslashes - * Kay Gürtzig 2018.02.12: Issue #4: Separate icons for FOR loops introduced - * Kay Gürtzig 2018.04.04 Issue #529: Critical section in prepareDraw() reduced. - * Kay Gürtzig 2018.07.12 Separator bug in For(String,String,String,int) fixed. - * Kay Gürtzig 2018.10.26 Enh. #619: Method getMaxLineLength() implemented + * Kay Gürtzig 2016-10-04 Enh. #253: Refactoring configuration revised + * Kay Gürtzig 2017-01-26 Enh. #259: Type retrieval support added (for counting loops) + * Kay Gürtzig 2017-04-14 Enh. #259: Approach to guess FOR-IN loop variable type too + * Kay Gürtzig 2017-04-30 Enh. #354: New structured constructors + * Kay Gürtzig 2017-11-02 Issue #447: Precaution against line-continuating backslashes + * Kay Gürtzig 2018-02-12: Issue #4: Separate icons for FOR loops introduced + * Kay Gürtzig 2018-04-04 Issue #529: Critical section in prepareDraw() reduced. + * Kay Gürtzig 2018-07-12 Separator bug in For(String,String,String,int) fixed. + * Kay Gürtzig 2018-10-26 Enh. #619: Method getMaxLineLength() implemented * Kay Gürtzig 2019-03-13 Issues #518, #544, #557: Element drawing now restricted to visible rect. + * Kay Gürtzig 2019-11-21 Enh. #739 Enum types considered in type compatibility check for FOR-IN lists * ****************************************************************************************************** * @@ -1233,7 +1234,7 @@ public void updateTypeMap(HashMap typeMap) { if (!this.isForInLoop()) { // This may be regarded as an explicit type declaration - this.addToTypeMap(typeMap, this.getCounterVar(), "int", 0, true, true, false); + this.addToTypeMap(typeMap, this.getCounterVar(), "int", 0, true, true); } // START KGU#261 2017-04-14: Enh. #259 Try to make as much sense of the value list as possible else { @@ -1247,11 +1248,25 @@ public void updateTypeMap(HashMap typeMap) typeSpec = itemType; } else if (!itemType.isEmpty() && !typeSpec.equalsIgnoreCase(itemType)) { - typeSpec = TypeMapEntry.combineTypes(itemType, typeSpec, true); + // START KGU#542 2019-11-21: Enh. #739 try a resolution if an enumerator type collides with int + //typeSpec = TypeMapEntry.combineTypes(itemType, typeSpec, true); + TypeMapEntry type1 = typeMap.get(":" + itemType); + TypeMapEntry type2 = typeMap.get(":" + typeSpec); + boolean isEnum1 = type1 != null && type1.isEnum(); + boolean isEnum2 = type2 != null && type2.isEnum(); + if (isEnum1 && typeSpec.equals("int") + || isEnum2 && itemType.equals("int") + || isEnum1 && isEnum2 && !type1.typeName.equals(type2.typeName)) { + typeSpec = "int"; + } + else { + typeSpec = TypeMapEntry.combineTypes(itemType, typeSpec, true); + } + // END KGU#542 2019-11-21 } } if (!typeSpec.isEmpty() && !typeSpec.equals("???")) { - this.addToTypeMap(typeMap, this.getCounterVar(), typeSpec, 0, true, false, false); + this.addToTypeMap(typeMap, this.getCounterVar(), typeSpec, 0, true, false); } } else { @@ -1261,7 +1276,7 @@ else if (!itemType.isEmpty() && !typeSpec.equalsIgnoreCase(itemType)) { typeSpec = identifyExprType(typeMap, valueListString, false); if (!typeSpec.isEmpty() && typeSpec.startsWith("@")) { // nibble one array level off as the loop variable is of the element type - this.addToTypeMap(typeMap, this.getCounterVar(), typeSpec.substring(1), 0, true, false, false); + this.addToTypeMap(typeMap, this.getCounterVar(), typeSpec.substring(1), 0, true, false); } } } diff --git a/src/lu/fisch/structorizer/elements/Instruction.java b/src/lu/fisch/structorizer/elements/Instruction.java index e9b16b0c..fd2dc340 100644 --- a/src/lu/fisch/structorizer/elements/Instruction.java +++ b/src/lu/fisch/structorizer/elements/Instruction.java @@ -68,6 +68,7 @@ * Kay Gürtzig 2019-02-14 Enh. #680: Improved support for processing of input instructions * Kay Gürtzig 2019-03-13 Issues #518, #544, #557: Element drawing now restricted to visible rect. * Kay Gürtzig 2019-03-18 Enh. #56: "preThrow" keyword handling + * Kay Gürtzig 2019-11-17 Enh. #739: Support for enum type definitions * ****************************************************************************************************** * @@ -81,6 +82,7 @@ import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.util.HashMap; +import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -515,6 +517,19 @@ protected void addFullText(StringList _lines, boolean _instructionsOnly) if (!isTypeDefinition(line, null)) { _lines.add(line); } + // START KGU#542 2019-11-17: Enh. #739 special treatment for enum type definitions + else if (isEnumTypeDefinition(line)) { + Root myRoot = getRoot(this); + HashMap constVals = myRoot.extractEnumerationConstants(line); + if (constVals != null) { + // FIXME If this interferes then we might generate singular constant definition lines + //this.constants.putAll(constVals); + for (Entry enumItem: constVals.entrySet()) { + _lines.add("const " + enumItem.getKey() + " <- " + enumItem.getValue()); + } + } + } + // END KGU#542 2019-11-17 } // END KGU#388 2017-09-13 // END KGU#413 2017-06-09 @@ -846,12 +861,14 @@ public boolean hasDeclarations() * a) type <id> = record{ <id> {, <id>} : <type> {; <id> {, <id>} : <type>} };
* b) type <id> = record{ <id> {, <id>} as <type> {; <id> {, <id>} as <type>} };
* c) type <id> = record{ <type> <id> {, <id>}; {; <type> <id> {, <id>}} };
- * d)...f) same as a)...c) but with struct instead of record.
- * e) type <id> = <type>
+ * d)...f) same as a)...c) but with struct instead of record;
+ * g) type <id> = enum{ <id> [ = <value> ] {, <id> [ = <value> ]} };
+ * h) type <id> = <type>.
* @param line - String comprising one line of code * @return true iff line is of one of the forms a) through e) * @see #isTypeDefinition(String, HashMap) * @see #isTypeDefinition() + * @see #isEnumTypeDefinition(String) */ public static boolean isTypeDefinition(String line) { @@ -863,8 +880,9 @@ public static boolean isTypeDefinition(String line) * a) type <id> = record{ <id> {, <id>} : <type> {; <id> {, <id>} : <type>} };
* b) type <id> = record{ <id> {, <id>} as <type> {; <id> {, <id>} as <type>} };
* c) type <id> = record{ <type> <id> {, <id>}; {; <type> <id> {, <id>}} };
- * d)...f) same as a)...c) but with struct instead of record.
- * e) type <id> = <type>
+ * d)...f) same as a)...c) but with struct instead of record;
+ * g) type <id> = enum{ <id> [ = <value> ] {, <id> [ = <value> ]} };
+ * h) type <id> = <type>.
* Type names and descriptions <type> are checked against existing types in {@code typeMap} if given. * @param line - String comprising one line of code * @param typeMap - if given then the type name must have been registered in typeMap in order to be accepted (otherwise @@ -882,16 +900,20 @@ public static boolean isTypeDefinition(String line, HashMap + * type <id> = enum{ <id> [ = <value> ] {, <id> [ = <value> ]} }.
+ * @param line - String comprising one line of code + * @return true iff line is of one of the forms a) through e) + * @see #isTypeDefinition(String, HashMap) + * @see #isTypeDefinition() + */ + public static boolean isEnumTypeDefinition(String line) + { + boolean isEnum = isTypeDefinition(line); + if (isEnum) { + int posEq = line.indexOf('='); + isEnum = posEq > 0 && TypeMapEntry.MATCHER_ENUM.reset(line.substring(posEq+1).trim()).matches(); + } + return isEnum; + } + // END KGU#542 2019-11-17 // START KGU#47 2017-12-06: Enh. #487 - compound check for hidable content /** @return true iff this Instruction contains nothing but type definitions and @@ -943,11 +984,17 @@ public boolean isMereDeclaratory() StringList lines = this.getUnbrokenText(); for (int i = 0; isHideable && i < lines.count(); i++) { String line = lines.get(i); - isHideable = line.isEmpty() || isTypeDefinition(line) || (isDeclaration(line) && !isAssignment(line)); + isHideable = line.isEmpty() || isMereDeclaration(line); } return isHideable; } // END KGU#477 2017-12-06 + // START KGU#772 2019-11-24: We want to be able to suppress expression of code for mere declarations + public static boolean isMereDeclaration(String line) + { + return isTypeDefinition(line) || (isDeclaration(line) && !isAssignment(line)); + } + // END KGU#772 2019-11-24 // START KGU#178 2016-07-19: Support for enh. #160 (export of called subroutines) // (This method is plaed here instead of in class Call because it is needed @@ -1074,7 +1121,7 @@ public void updateTypeMapFromLine(HashMap typeMap, String for (int i = 0; i < varTokens.count(); i++) { if (Function.testIdentifier(varTokens.get(i), null) && (i + 1 >= varTokens.count() || varTokens.get(i+1).equals(","))) { - addToTypeMap(typeMap, varTokens.get(i), typeSpec, lineNo, isAssigned, true, false); + addToTypeMap(typeMap, varTokens.get(i), typeSpec, lineNo, isAssigned, true); } } } @@ -1091,8 +1138,8 @@ else if (posAsgnmt > 0 && !token0.equals("var") && !token0.equals("dim")) { StringList rightSide = tokens.subSequence(posAsgnmt+1, tokens.count()); isAssigned = !rightSide.isEmpty(); // Isolate the variable name from the left-hand side of the assignment - varName = getAssignedVarname(leftSide); - // Without const, var, or dim a declaration must be a C-style declaration + varName = getAssignedVarname(leftSide, false); + // Without const, var, or dim, a declaration must be a C-style declaration boolean isCStyleDecl = Instruction.isDeclaration(line); // If the target is a record component we won't add a type specification. if (varName != null && !varName.contains(".")) { @@ -1119,20 +1166,46 @@ else if (posAsgnmt > 0 && !token0.equals("var") && !token0.equals("dim")) { } } } - addToTypeMap(typeMap, varName, typeSpec, lineNo, isAssigned, isDeclared || isCStyleDecl, isCStyleDecl); + addToTypeMap(typeMap, varName, typeSpec, lineNo, isAssigned, isDeclared || isCStyleDecl); } // START KU#388 2017-08-07: Enh. #423 else if (isTypeDefinition(line, typeMap)) { - // FIXME: In future, array type definitions are also to be handled... + // START KGU#542 2019-11-17: Enh. #739 + boolean isEnum = tokens.get(3).equalsIgnoreCase("enum"); + // END KGU#542 2019-11-17 + // FIXME: In future, array type definitions will also have to be handled... String typename = tokens.get(1); // Because of possible C-style declarations we must not glue the tokens together with "". typeSpec = tokens.concatenate(null, 3, tokens.count()).trim(); int posBrace = typeSpec.indexOf("{"); if (posBrace > 0 && tokens.get(tokens.count()-1).equals("}")) { - StringList compNames = new StringList(); - StringList compTypes = new StringList(); - this.extractDeclarationsFromList(typeSpec.substring(posBrace+1, typeSpec.length()-1), compNames, compTypes, null); - addRecordTypeToTypeMap(typeMap, typename, typeSpec, compNames, compTypes, lineNo); + // START KGU#542 2019-11-17: Enh. #739 Handle enumeration tapes + if (isEnum) { + // first make sure the syntax is okay + if (TypeMapEntry.MATCHER_ENUM.reset(typeSpec).matches() ) { + Root root = getRoot(this); + if (root != null) { + TypeMapEntry enumType = new TypeMapEntry(typeSpec, typename, typeMap, this, lineNo, false, false); + typeMap.put(":" + typename, enumType); + HashMap enumItems = root.extractEnumerationConstants(line); + if (enumItems != null) { + for (String constName: enumItems.keySet()) { + typeMap.put(constName, enumType); + } + } + } + + } + } + else { + // END KGU#542 2019-11-17 + StringList compNames = new StringList(); + StringList compTypes = new StringList(); + this.extractDeclarationsFromList(typeSpec.substring(posBrace+1, typeSpec.length()-1), compNames, compTypes, null); + addRecordTypeToTypeMap(typeMap, typename, typeSpec, compNames, compTypes, lineNo); + // START KGU#542 2019-11-17: Enh. #739 + } + // END KGU#542 2019-1-17 } else { // According to isTypeefinition() this must now be an alias for an existing type @@ -1143,17 +1216,23 @@ else if (isTypeDefinition(line, typeMap)) { } /** - * Extracts the target variable name out of the given blank-free token sequence which may comprise - * the entire line of an assignment or just its left part. + * Extracts the target variable name (or the the entire variable expression, see argument + * {@code entireTarget} out of the given blank-free token sequence which may comprise + * the entire line of an assignment or just its left part.
* The variable name may be qualified, i.e. be a sequence of identifiers separated by dots. + * Possible end-standing indices will not be part of the returned string, e.g. the result for + * {@code foo.bar[i][j]} will be "foo.bar", whereas for a mixed expression {@code foo[i].bar[j]} + * the result would be just "foo". * @param tokens - unified tokens of an assignment instruction without whitespace (otherwise the result may be nonsense) + * @param entireTarget if this is true then index expressions etc. will remain in the result + * (so it is no longer the pure name) * @return the extracted variable name or null */ // KGU#686 2019-03-17: Enh. #56 - made static to facilitate implementation of Try - public static String getAssignedVarname(StringList tokens) { + public static String getAssignedVarname(StringList tokens, boolean entireTarget) { String varName = null; // START KGU#689 2019-03-21: Issue #706 - get along with named parameter calls - tokens = coagulateSubexpressions(tokens); + tokens = coagulateSubexpressions(tokens.copy()); // END KGU689 2019-03-21 int posAsgn = tokens.indexOf("<-"); if (posAsgn > 0) { @@ -1173,21 +1252,58 @@ public static String getAssignedVarname(StringList tokens) { tokens = tokens.subSequence(0, posColon); } // END KGU#388 2017-09-15 - // The last sequence of dot.separated ids should be the variable name + // The last sequence of dot-separated ids should be the variable name if (tokens.count() > 0) { int i = tokens.count()-1; varName = tokens.get(i); + // START KGU#780 2019-12-01: Bugfix - endstanding index access was erroneously returned + // FIXME But it might be even more complicated, e.g. foo[i].bar[j]! + while (varName.startsWith("[") && varName.endsWith("]") && i > 0) { + if (posColon >= 0) { + // Something is wrong here - there should not be be both a declaration and a bracket(?) + return null; + } + // It is a coagulated index access - skip it + varName = tokens.get(--i); + } + // END KGU#780 2019-12-01 // START KGU#388 2017-09-14: Enh. #423 - while (i > 1 && tokens.get(i-1).equals(".") && Function.testIdentifier(tokens.get(i-2), null)) { - varName = tokens.get(i-2) + "." + varName; - i -= 2; + // START KGU#780 2019-12-01: In cases like foo[i].bar[j] we want to return rather "foo" than "bar" + //while (i > 1 && tokens.get(i-1).equals(".") && Function.testIdentifier(tokens.get(i-2), null)) { + // varName = tokens.get(i-2) + "." + varName; + // i -= 2; + //} + while (i > 1 && varName != null && tokens.get(i-1).equals(".")) { + String preDotToken = tokens.get(i-2); + if (Function.testIdentifier(preDotToken, null)) { + varName = tokens.get(i-2) + "." + varName; + i -= 2; + } + else { + // We may expect either an index expression or an identifier (variable or component name) + while (i > 1 && preDotToken.startsWith("[") && preDotToken.endsWith("]")) { + // Skip index expressions (invalidate the name, it was a component of an array element) + varName = null; + preDotToken = tokens.get(--i - 2); + } + if (varName == null && Function.testIdentifier(preDotToken, null)) { + varName = preDotToken; // Start again with the identifier prior to the indices + i -= 2; // this ought to be the token index of varName + } + } } + // END KGU#780 2019-12-01 // END KGU#388 2017-09-14 + // START KGU#784 2019-12-02 + if (entireTarget) { + varName = tokens.concatenate(null, i); + } + // END KGU#784 2019-12-02 } return varName; } // END KGU#261 2017-01-26 - + // START KGU#261 2017-02-20: Enh. #259 Allow CALL elements to override this... /** * Tries to extract type information from the right side of an assignment. @@ -1217,6 +1333,17 @@ else if (!itemType.isEmpty() && !typeSpec.equalsIgnoreCase(itemType)) { typeSpec += "[" + items.count() + "]"; } else { + // START KGU#542 2019-11-17: Enh. #739 Check for enumerator constant + if (rightSide.count() == 1 && Function.testIdentifier(rightSide.get(0), null)) { + Root root = getRoot(this); + if (root != null) { + String constVal = root.constants.get(rightSide.get(0)); + if (constVal != null && constVal.startsWith(":") && constVal.contains("€")) { + return constVal.substring(1, constVal.indexOf('€')); // This is the type name + } + } + } + // END KGU#542 2019-11-17 // Try to derive the type from the expression typeSpec = identifyExprType(knownTypes, rightSide.concatenate(" "), false); } @@ -1235,8 +1362,8 @@ protected String getTypeFromTypeDefinition(StringList rightSide, HashMap getVariableSetFor(Element _element) // START KGU#375 2017-03-31: Enh. #388 /** - * Names and cached value expressions of detected constants among the {@link #variables} + * Names and cached value expressions of detected constants among the {@link #variables}. + * For enumeration type constants, the actual value is prefixed with ":" + typename + "€". + * @see #getConstValueString(String) */ public LinkedHashMap constants = new LinkedHashMap(); // END KGU#375 2017-03-31 @@ -2754,7 +2760,7 @@ private void skimRecordInitializers(StringList tokens) { int posBrace = 0; while ((posBrace = tokens.indexOf("{", posBrace+1)) > 0) { if (Function.testIdentifier(tokens.get(posBrace-1), null)) { - HashMap components = Element.splitRecordInitializer(tokens.concatenate("", posBrace-1), null); + HashMap components = Element.splitRecordInitializer(tokens.concatenate("", posBrace-1), null, false); if (components != null) { // Remove all tokens from the type name on (they are in the HashMap now) tokens.remove(posBrace-1, tokens.count()); @@ -2777,6 +2783,26 @@ private void skimRecordInitializers(StringList tokens) { } } // END KGU#388 2017-10-09 + + // START KGU#542 2019-11-17: Enh. #739 Support for enumeration type values + /** + * Returns the value string (cached literal or expression) associated to constant + * {@code constName} (if it was defined) or null (otherwise). In case of enumeration + * constants, wipes off the typename prefix ({@code ":" + + "€"}). + * @param constName - name of the constant + * @return value string for the constant (cleaned in case of an enumerator) or null + * @see #constants + */ + public String getConstValueString(String constName) + { + String valString = this.constants.get(constName); + if (valString != null && valString.startsWith(":") && valString.contains("€")) { + // Skim off the enumerator type name + valString = valString.substring(valString.indexOf('€')+1); + } + return valString; + } + // END KGU#542 2019-11-17 // KGU 2016-03-29 Rewritten based on tokens /** @@ -2914,15 +2940,17 @@ public StringList retrieveVarNames() /** * Provides all variable names of the entire program if cached, otherwise retrieves and - * stores them in this.variables. + * stores them in {@link #variables}. * @return list of variable names * @see #retrieveVarNames() + * @see #getMereDeclarationNames() */ public StringList getVarNames() { //System.out.println("getVarNames() called..."); if (this.variables != null) { return this.variables; } + // This is the same as retrieveVarNames() return getVarNames(this, false, false, true); } @@ -2982,6 +3010,15 @@ private StringList getVarNames(Element _ele, boolean _onlyEle, boolean _onlyBody int i = 0; while (i < lines.count()) { if (Instruction.isTypeDefinition(lines.get(i), null)) { + // START KGU#542 2019-11-17: Enh. #739 We must extract enumerators here + HashMap constVals = this.extractEnumerationConstants(lines.get(i)); + if (constVals != null) { + // We simply generate singular constant definition lines + for (Entry enumItem: constVals.entrySet()) { + lines.insert("const " + enumItem.getKey() + " <- " + enumItem.getValue(), i++); + } + } + // END KGU#542 2019-11-17 lines.remove(i); } else { @@ -3016,6 +3053,93 @@ else if (_entireProg) return varNames; } + /** + * Retrieves all constants from the given type definition list if it is an + * enumeration type list and returns their name-value map.
+ * The associated values will be prefixed with {@code ":" + + "€"} and may be + * constant expressions, particularly of kind {@code +}. + * @param _typeDefLine - the (unbroken) line of the enum type definition + * @returns a map of the enumeration constants to their prefixed values strings or null + */ + public LinkedHashMap extractEnumerationConstants(String _typeDefLine) + { + LinkedHashMap enumConstants = null; + StringList tokens = Element.splitLexically(_typeDefLine, true); + tokens.removeAll(" "); + if (!tokens.get(3).equalsIgnoreCase("enum")) { + return null; + } + String typename = tokens.get(1); + String typeSpec = tokens.concatenate(null, 3, tokens.count()).trim(); + // Confirm that the syntax is okay + if (TypeMapEntry.MATCHER_ENUM.reset(typeSpec).matches()) { + enumConstants = new LinkedHashMap(); + int val = 0; + String valStr = ""; + int posBrace = typeSpec.indexOf('{'); + StringList items = StringList.explode(typeSpec.substring(posBrace+1, typeSpec.length()-1), ","); + for (int i = 0; i < items.count(); i++, val++) { + String item = items.get(i); + int posEq = item.indexOf('='); + if (posEq >= 0) { + // Get the value string + valStr = item.substring(posEq+1).trim(); + val = 0; + // Reduce item to the pure constant name + item = item.substring(0, posEq); + // FIXME: We should be able to evaluate constant expressions, e.g. "MONDAY+1"! + if (this.constants.containsKey(valStr)) { + // Is an already defined constant, get the associated value string + valStr = this.getConstValueString(valStr); + } + else if (valStr.contains("+")) { + int posPlus = valStr.lastIndexOf('+'); + try { + int offset = Integer.parseInt(valStr.substring(posPlus+1)); + valStr = valStr.substring(0, posPlus).trim(); + val = offset; + } + catch (NumberFormatException ex) {} + } + try { + int val0 = Integer.parseInt(valStr); + // Don't accept negative values + if (val0 >= 0) { + val = val0; + valStr = ""; + } + } + catch (NumberFormatException ex) { + // Just ignore the explicit value and use the standard + } + } + enumConstants.put(item, ":" + typename + "€" + valStr + (!valStr.isEmpty() ? "+" : "") + val); + } + } + return enumConstants; + } + + // START KGU#672 2019-11-13: Introduced for Bugfix #762 + /** + * @return A list of the names of uninitialized, i.e. merely declared, variables + * (of this diagram and all included diagrams). + * @see #getVarNames() + * @see #getTypeInfo() + */ + public StringList getMereDeclarationNames() + { + StringList declNames = new StringList(); // Result + StringList varNames = this.getVarNames(); // Names of initialized variables + for (String name: this.getTypeInfo().keySet()) { + // Ignore type names and omit initialized variables (which should also include constants) + if (!name.startsWith(":") && !varNames.contains(name)) { + declNames.add(name); + } + } + return declNames; + } + // END KGU#672 2019-11-13 + // START KGU#261 2017-01-20: Enh. #259 /** * Creates (if not already cached), caches, and returns the static overall type map @@ -3133,7 +3257,7 @@ public void updateTypeMap(HashMap typeMap) String typeSpec = null; for (Param par: parameters) { if ((typeSpec = par.getType()) != null) { - this.addToTypeMap(typeMap, par.getName(), typeSpec, 0, true, true, false); + this.addToTypeMap(typeMap, par.getName(), typeSpec, 0, true, true); } } if (this.isSubroutine()) { @@ -3145,7 +3269,7 @@ public void updateTypeMap(HashMap typeMap) // consideration where we check whether an explicit variable declaration will come (mostly C++, // C#, Java) we drive better if we don't set the "explicitly" flag here. //this.addToTypeMap(typeMap, this.getMethodName(), typeSpec, 0, false, true, false); - this.addToTypeMap(typeMap, this.getMethodName(), typeSpec, 0, false, false, false); + this.addToTypeMap(typeMap, this.getMethodName(), typeSpec, 0, false, false); // END KGU#593 2018-10-05 } } @@ -4400,7 +4524,7 @@ private void analyse_22_24(Instruction _instr, Vector _errors, St else if (line.startsWith("type ") || isTypedef) { if (!isTypedef) { //error = new DetectedError("Type definition in line"+i+"is malformed!", _instr); - addError(_errors, new DetectedError(errorMsg(Menu.error24_1, String.valueOf(i)), _instr), 24); + addError(_errors, new DetectedError(errorMsg(Menu.error24_1, String.valueOf(i)), _instr), 24); } else { StringList tokens = splitLexically(line, true); @@ -4418,29 +4542,55 @@ else if (line.startsWith("type ") || isTypedef) { //error = new DetectedError("Type name «" + typename + "» is illegal or colliding with another identifier.", _instr); addError(_errors, new DetectedError(errorMsg(Menu.error24_2, typename), _instr), 24); } - this.extractDeclarationsFromList(typeSpec.substring(posBrace+1, typeSpec.length()-1), compNames, compTypes, null); - for (int j = 0; j < compNames.count(); j++) { - String compName = compNames.get(j); - if (!Function.testIdentifier(compName, null) || compNames.subSequence(0, j-1).contains(compName)) { - //error = new DetectedError("Component name «" + compName + "» is illegal or duplicate.", _instr); - addError(_errors, new DetectedError(errorMsg(Menu.error24_3, compName), _instr), 24); + // START KGU#542 2019-11-17: Enh. #739 support enum types now + String tag = typeSpec.substring(0, posBrace).toLowerCase(); + if (tag.equals("enum")) { + HashMap enumDefs = this.extractEnumerationConstants(line); + if (enumDefs == null) { + //error = new DetectedError("Type definition in line"+i+"is malformed!", _instr); + addError(_errors, new DetectedError(errorMsg(Menu.error24_1, String.valueOf(i)), _instr), 24); } - String type = compTypes.get(j).trim(); - // Clear off array specifiers, but the check is still too restrictive... - if (type != null) { - String typeLower; - if (type.endsWith("]") && type.contains("[")) { - type = type.substring(0, type.indexOf("[")).trim(); + else { + for (Entry enumItem: enumDefs.entrySet()) { + String constName = enumItem.getKey(); + String enumValue = enumItem.getValue(); + String oldVal = _definedConsts.put(constName, enumValue); + if (oldVal != null && !oldVal.equals(enumValue)) { + //error = new DetectedError("Attempt to modify the value of constant «"+varName+"»!", _instr); + addError(_errors, new DetectedError(errorMsg(Menu.error22_2, constName), _instr), 22); + } } - else if ((typeLower = type.toLowerCase()).startsWith("array") && typeLower.contains("of ")) { - type = type.substring(typeLower.lastIndexOf("of ")+3).trim(); + } + } + else { // tag assumed to be "record" or "struct" + // END KGU#542 2019-11-17 + this.extractDeclarationsFromList(typeSpec.substring(posBrace+1, typeSpec.length()-1), compNames, compTypes, null); + for (int j = 0; j < compNames.count(); j++) { + String compName = compNames.get(j); + if (!Function.testIdentifier(compName, null) || compNames.subSequence(0, j-1).contains(compName)) { + //error = new DetectedError("Component name «" + compName + "» is illegal or duplicate.", _instr); + addError(_errors, new DetectedError(errorMsg(Menu.error24_3, compName), _instr), 24); } - if (!TypeMapEntry.isStandardType(type) && !_types.containsKey(":" + type) && !type.equals(typename)) { - //error = new DetectedError("Type name «" + type + "» is illegal or unknown.", _instr); - addError(_errors, new DetectedError(errorMsg(Menu.error24_4, type), _instr), 24); + String type = compTypes.get(j); + // Clear off array specifiers, but the check is still too restrictive... + if (type != null) { + type = type.trim(); + String typeLower; + if (type.endsWith("]") && type.contains("[")) { + type = type.substring(0, type.indexOf("[")).trim(); + } + else if ((typeLower = type.toLowerCase()).startsWith("array") && typeLower.contains("of ")) { + type = type.substring(typeLower.lastIndexOf("of ")+3).trim(); + } + if (!TypeMapEntry.isStandardType(type) && !_types.containsKey(":" + type) && !type.equals(typename)) { + //error = new DetectedError("Type name «" + type + "» is illegal or unknown.", _instr); + addError(_errors, new DetectedError(errorMsg(Menu.error24_4, type), _instr), 24); + } } } + // START KGU#542 2019-11-17: Enh. #739 support enum types now } + // END KGU#542 2019-11-17 // START KGU#543 2018-07-05 - check if it is a valid type reference } else if (Function.testIdentifier(typeSpec, null) && !_types.containsKey(":" + typeSpec)) { @@ -4480,7 +4630,7 @@ else if (Function.testIdentifier(typeSpec, null) && !_types.containsKey(":" + ty else { // START KGU#559 2018-07-20: Enh. #563 more intelligent initializer evaluation //HashMap components = Element.splitRecordInitializer(tokens.concatenate("", posBrace)); - HashMap components = Element.splitRecordInitializer(tokens.concatenate("", posBrace), recType); + HashMap components = Element.splitRecordInitializer(tokens.concatenate("", posBrace), recType, false); // END KGU#559 2018-07-20 Set compNames = recType.getComponentInfo(true).keySet(); for (String compName: compNames) { @@ -4744,7 +4894,7 @@ private void analyse_27_28(Case _case, Vector _errors) HashSet values = new HashSet(); StringList text = _case.getUnbrokenText(); StringList duplicates = new StringList(); - boolean nonNumbers = false; + String aNonNumber = null; for (int i = 1; i < text.count(); i++) { StringList items = Element.splitExpressionList(text.get(i), ","); for (int j = 0; j < items.count(); j++) { @@ -4752,11 +4902,11 @@ private void analyse_27_28(Case _case, Vector _errors) String item = items.get(j); // Check for duplicates (including the default label) if (!selectors.add(item)) { - duplicates.add(item); + duplicates.addIfNew(item); } // Check for non-integers and non-characters (without the default branch label) - if (j < items.count()-1) { - String constVal = this.constants.get(item); + if (i < text.count()-1) { + String constVal = this.getConstValueString(item); if (constVal == null) { constVal = item; } @@ -4769,15 +4919,15 @@ private void analyse_27_28(Case _case, Vector _errors) } } catch (NumberFormatException ex) { - nonNumbers = true; + aNonNumber = item; } } } } } - if (nonNumbers) { + if (aNonNumber != null) { //error = new DetectedError("Some selector item seems not to be an integer constant.", _case); - addError(_errors, new DetectedError(Menu.error27.getText(), _case), 27); + addError(_errors, new DetectedError(errorMsg(Menu.error27, aNonNumber), _case), 27); } if (!duplicates.isEmpty()) { //error = new DetectedError("There are multiple (conflicting) selector items (%) in the CASE element!", _case); diff --git a/src/lu/fisch/structorizer/elements/Try.java b/src/lu/fisch/structorizer/elements/Try.java index 402e1047..951a0c7d 100644 --- a/src/lu/fisch/structorizer/elements/Try.java +++ b/src/lu/fisch/structorizer/elements/Try.java @@ -506,7 +506,7 @@ public void updateTypeMap(HashMap typeMap) //} String excName = this.getExceptionVarName(); if (excName != null) { - addToTypeMap(typeMap, excName, "Exception", 0, true, true, false); + addToTypeMap(typeMap, excName, "Exception", 0, true, true); } } @@ -532,7 +532,8 @@ protected Set getVariableSetFor(Element _child) { public String getExceptionVarName() { return Instruction.getAssignedVarname( - Element.splitLexically(this.getUnbrokenText().getLongString(), true) + Element.splitLexically(this.getUnbrokenText().getLongString(), true), + false ); } diff --git a/src/lu/fisch/structorizer/elements/TypeMapEntry.java b/src/lu/fisch/structorizer/elements/TypeMapEntry.java index e9d3c2c3..62d417b1 100644 --- a/src/lu/fisch/structorizer/elements/TypeMapEntry.java +++ b/src/lu/fisch/structorizer/elements/TypeMapEntry.java @@ -19,8 +19,6 @@ */ package lu.fisch.structorizer.elements; -import java.util.HashMap; - /****************************************************************************************************** * * Author: Kay Gürtzig @@ -43,6 +41,8 @@ * Kay Gürtzig 2017.09.22 Bugfix #428 Defective replacement pattern for "short" in canonicalizeType(String) * Kay Gürtzig 2017.09.29 Regex stuff revised (final Strings -> final Patterns) * Kay Gürtzig 2018.07.12 Canonicalisation of type name "unsigned short" added. + * Kay Gürtzig 2019-11-17 Field isCStyle removed, several method signatures accordingly reduced, + * Enh. #739: Support for enum types * ****************************************************************************************************** * @@ -65,6 +65,7 @@ * ******************************************************************************************************/// +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -104,6 +105,10 @@ public class TypeMapEntry { private static final Pattern ARRAY_PATTERN5 = Pattern.compile("(.*?)\\[.*?\\]$"); //private static final Pattern RANGE_PATTERN = Pattern.compile("^([0-9]+)[.][.][.]?([0-9]+)$"); private static final Pattern RANGE_PATTERN = Pattern.compile("^([0-9]+)\\s*?[.][.][.]?\\s*?([0-9]+)$"); + // START KGU#542 2019-11-17: Enh. #739 + public static final Matcher MATCHER_ENUM = Pattern.compile("^" + BString.breakup("enum") + + "\\s*[{]\\s*[A-Za-z_][A-Za-z_0-9]*\\s*([=]\\s*[^=,}]*?)?(,\\s*[A-Za-z_][A-Za-z_0-9]*(\\s*[=]\\s*[^=,}]*?)?)*\\s*[}]$").matcher(""); + // END KGU#542 2019-11-17 // START KGU#686 2019-03-16: Enh. #56 - facilitate type retrieval by a backlink to the type map private HashMap typeMap = null; @@ -123,27 +128,88 @@ class VarDeclaration { // START KGU#388 2017-07-04: Enh. #423 New structure for record types public LinkedHashMap components = null; // END KGU#388 2017-07-04 - public boolean isCStyle = false; + // START KGU#542 2019-11-17: Enh. #739 Support for enumeration types + public StringList valueNames = null; // enumerated value names (to be retrieved from Root.constants) + // END KGU#542 2019-11-17 - public VarDeclaration(String _descriptor, Element _element, int _lineNo, boolean _cStyle) + /** + * Creates a new declaration for non-record type (may be an array type or an + * enum type). For record types please preprocess the component info and use + * {@link VarDeclaration#VarDeclaration(String, Element, int, LinkedHashMap)} + * instead. For enum types, the values must be extracted and assigned to the + * {@link Root} constants map by the caller.
+ * Usually, you should not call this directly but use one of the {@link TypeMapEntry} + * constructors or methods referred to below. + * @param _descriptor + * @param _element + * @param _lineNo + * @see VarDeclaration#VarDeclaration(String, Element, int, LinkedHashMap) + * @see TypeMapEntry#TypeMapEntry(String, String, HashMap, Element, int, boolean, boolean) + * @see TypeMapEntry#addDeclaration(String, Element, int, boolean) + */ + public VarDeclaration(String _descriptor, Element _element, int _lineNo) { typeDescriptor = _descriptor.trim(); definingElement = _element; lineNo = _lineNo; + // FIXME: shouldn't we apply the ARRAY_PATTERNs here? boolean isArray = (typeDescriptor.matches(".+\\[.*\\].*") || typeDescriptor.matches("(^|\\W.*)" + BString.breakup("array") + "($|\\W.*)")); if (isArray) { this.setElementType(); this.setIndexRanges(); } - isCStyle = _cStyle; + // START KGU#542 2019-11-17 + else if (MATCHER_ENUM.reset(typeDescriptor).matches()) { + int start = typeDescriptor.indexOf('{') + 1; + this.valueNames = StringList.explode(typeDescriptor.substring(start, typeDescriptor.length()-1), "\\s*,\\s*"); +// Root root = null; +// if (_element != null) { +// root = Element.getRoot(_element); +// } +// int val = 0; +// for (int i = 0; i < this.valueNames.count(); i++, val++) { +// String item = this.valueNames.get(i); +// int posEq = item.indexOf('='); +// if (posEq >= 0) { +// // Remove the value itst +// this.valueNames.set(i, item.substring(0, posEq)); +// String valStr = item.substring(posEq+1).trim(); +// if (valStr.startsWith("=")) { +// valStr = valStr.substring(1); +// } +// if (root != null) { +// if (root.constants.containsKey(valStr)) { +// valStr = root.constants.get(valStr); +// if (valStr.startsWith(":") && valStr.contains("€")) { +// valStr = valStr.substring(valStr.indexOf('€', 1)); +// } +// } +// try { +// val = Integer.parseInt(valStr); +// root.constants.put(key, value) +// } +// catch (NumberFormatException ex) { +// // Just ignore the value +// } +// } +// } +// } + } + // END KGU#542 2019-11-17 } /** - * Creates a new Type definition for a record type + * Creates a new type definition for a record type (for non-record types use + * {@link VarDeclaration#VarDeclaration(String, Element, int)}.
+ * Usually, you should not call this directly but use one of the {@link TypeMapEntry} + * constructors or methods referred to below. * @param _descriptor - textual description of the type * @param _element - originating element (should be an Instruction with a type definition) * @param _lineNo - line no within the element * @param _components - the ordered map of declared components + * @see VarDeclaration#VarDeclaration(String, Element, int) + * @see TypeMapEntry#TypeMapEntry(String, String, HashMap, LinkedHashMap, Element, int) + * @see TypeMapEntry#addDeclaration(String, Element, int, boolean) */ public VarDeclaration(String _descriptor, Element _element, int _lineNo, LinkedHashMap _components) @@ -151,12 +217,14 @@ public VarDeclaration(String _descriptor, Element _element, int _lineNo, typeDescriptor = _descriptor.trim(); definingElement = _element; lineNo = _lineNo; - components = _components; + components = _components; } /** * Indicates whether this declaration bears some evidence of an array structure * @return true if this refers to an indexed type. + * @see #isEnum() + * @see #isRecord() */ public boolean isArray() { @@ -167,6 +235,8 @@ public boolean isArray() /** * Indicates whether this declaration represents a record structure * @return true if this refers to a structured type. + * @see #isArray() + * @see #isEnum() */ public boolean isRecord() { @@ -174,10 +244,26 @@ public boolean isRecord() } // END KGU#388 2017-07-04 + // START KGU#542 2019-11-17: Enh- #739 - support for enumerator types + /** + * Indicates whether this declaration represents an enumerator type + * @return true if this refers to an enumerator type + * @see #isArray() + * @see #isRecord() + */ + public boolean isEnum() + { + return this.valueNames != null; + } + // END KGU#542 2019-11-17 + /** * Returns a type string with canonicalized structure information, i.e. * the original element type name, prefixed with as many '@' characters - * as there are index levels if it is an array type. + * as there are index levels if it is an array type. If it is a record type then + * it will enumerate semicolon-separated name:type_name pairs within braces after + * a '$' prefix. An enumerator type will enumerate the value names (constant ids) + * separated by commas within braces after an '€' sign. * @see TypeMapEntry#getTypes() * @return type string, possibly prefixed with one or more '@' characters. */ @@ -193,7 +279,10 @@ public String getCanonicalType() * possible, i.e. type names like "integer", "real" etc. apparently designating * standard types will be replaced by corresponding Java type names), all * prefixed with as many '@' characters as there are index levels if it - * is an array type. + * is an array type. If it is a record type then it will enumerate semicolon- + * separated name:type_name pairs within braces after a '$' prefix. An enumerator + * type will enumerate the value names (constant ids) separated by commas within + * braces following an '€' prefix. * @param canonicalizeTypeNames - specifies whether type names are to be unified, too * @see TypeMapEntry#getTypes() * @return type string, possibly prefixed with one or more '@' characters. @@ -216,6 +305,12 @@ else if (this.isRecord()) { type = "${" + compDescr.concatenate(";") + "}"; } // END KGU#388 2017-07-04 + // START KGU#542 2019-11-17: Enh. #739 + else if (this.isEnum()) { + type = "€{" + this.valueNames.concatenate(",") + "}"; + canonicalizeTypeNames = false; // Nothing to canonicalize + } + // END KGU#542 2019-11-17 if (canonicalizeTypeNames) { type = canonicalizeType(type); } @@ -335,18 +430,20 @@ private TypeMapEntry() /** * Analyses the given declaration information and creates a corresponding - * entry (with a single declaration record). - * @see #addDeclaration(String _descriptor, Element _element, int _lineNo, boolean _initialized, boolean _cStyle) + * entry (with a single declaration object).
+ * NOTE: For record types use {@link TypeMapEntry#TypeMapEntry(String, String, HashMap, LinkedHashMap, Element, int)} + * instead. * @param _descriptor - the found type-describing or -specifying string * @param _typeName - the type name if this is a type definition, null otherwise (enh. #423, 2017-07-12) - * @param _owningMap TODO + * @param _owningMap - the type map this entry is to be added to (or null if not known) * @param _element - the originating Structorizer element * @param _lineNo - the line number within the element text * @param _initialized - whether the variable is initialized or assigned here * @param _explicit - whether this is an explicit variable declaration (or just derived from value) - * @param _cStyle - whether it's a C-style declaration or initialization + * @see #addDeclaration(String _descriptor, Element _element, int _lineNo, boolean _initialized) + * @see TypeMapEntry#TypeMapEntry(String, String, HashMap, LinkedHashMap, Element, int) */ - public TypeMapEntry(String _descriptor, String _typeName, HashMap _owningMap, Element _element, int _lineNo, boolean _initialized, boolean _explicit, boolean _cStyle) + public TypeMapEntry(String _descriptor, String _typeName, HashMap _owningMap, Element _element, int _lineNo, boolean _initialized, boolean _explicit) { // START KGU#388 2017-07-12: Enh. #423 this.typeName = _typeName; @@ -354,7 +451,7 @@ public TypeMapEntry(String _descriptor, String _typeName, HashMap + * For non-record types use {@link TypeMapEntry#TypeMapEntry(String, String, HashMap, Element, int, boolean, boolean)} + * instead. * @param _descriptor - the found type-describing or -specifying string * @param _typeName - the type name if this is a type definition (mandatory!) * @param _owningMap - the type map this entry is going to be put to * @param _components - the component type map - FIXME - may we replace this by a simple type name list now? * @param _element - the originating Structorizer element * @param _lineNo - the line number within the element text + * @see TypeMapEntry#TypeMapEntry(String, String, HashMap, Element, int, boolean, boolean) + * @see #addDeclaration(String _descriptor, Element _element, int _lineNo, boolean _initialized) */ public TypeMapEntry(String _descriptor, String _typeName, HashMap _owningMap, LinkedHashMap _components, Element _element, int _lineNo) @@ -499,15 +599,17 @@ public static boolean isStandardType(String typeName) * Analyses the given declaration information and adds a corresponding * declaration info to this entry if it differs. * It will even be added if this entry is marked as (explicitly) declared - * such that analysis may find out potential conflicts + * such that analysis may find out potential conflicts.
+ * Note that in case of an enumeration type, the caller must add the respective + * constant values to the {@link Root#constants} map if {@code _element} isn't + * given or isn't linked to its owning {@link Root}. * @param _descriptor - the found type-describing or -specifying string * @param _element - the originating Structorizer element * @param _lineNo - the line number within the element text * @param _initialized - whether the variable is initialized or assigned here - * @param _cStyle - whether it's a C-style declaration or initialization * @return indicates whether the new declaration substantially differs from previous ones */ - public boolean addDeclaration(String _descriptor, Element _element, int _lineNo, boolean _initialized, boolean _cStyle) + public boolean addDeclaration(String _descriptor, Element _element, int _lineNo, boolean _initialized) { boolean differs = false; boolean isNew = true; @@ -522,7 +624,7 @@ public boolean addDeclaration(String _descriptor, Element _element, int _lineNo, } } if (isNew) { - declarations.addLast(new VarDeclaration(_descriptor, _element, _lineNo, _cStyle)); + declarations.addLast(new VarDeclaration(_descriptor, _element, _lineNo)); } if (_initialized) { modifiers.add(_element); @@ -612,7 +714,7 @@ public StringList getTypes(boolean canonicalizeTypeNames) /** * If this is a defined record type, returns the component-type map * @param _merge - whether concurring definitions are to be merged. - * @return an ordered table mapping component names to defining TypeMapEntries + * @return an ordered table, mapping component names to defining TypeMapEntries, or null */ public LinkedHashMap getComponentInfo(boolean _merge) { @@ -638,30 +740,30 @@ public LinkedHashMap getComponentInfo(boolean _merge) return componentInfo; } // END KGU#388 2017-09-13 - - /** - * Checks if there is a C-style declaration for this variable in _element - * or in the first declaring element (if _element = null) - * @param _element - the interesting element or null - * @return true if the first matching declaration uses C syntax - */ - public boolean isCStyleDeclaredAt(Element _element) + + // START KGU#542 2019-11-17: Enh. #739 - Support for enum types + public StringList getEnumerationInfo() { - for (VarDeclaration currDecl: declarations) { - if (_element == null || currDecl.definingElement == _element) { - return currDecl.isCStyle; - } + if (this.isEnum()) { + for (VarDeclaration varDecl: this.declarations) { + if (varDecl.isEnum()) { + if (varDecl.valueNames != null) { + return varDecl.valueNames.copy(); + } + } //if (varDecl.isEnum()) + } // for (VarDeclaration varDecl: this.declarations) } - return false; + return null; } - + // END KGU#542v 2019-11-17 + /** * Indicates whether at least the first declaration states that the type * is an array (this may be in conflict with other declarations, though) + * @return true if there is some evidence of an array structure * @see #isArray(boolean) * @see #isRecord() - * @see #isRecord(boolean) - * @return true if there is some evidence of an array structure + * @see #isEnum() */ public boolean isArray() { @@ -674,8 +776,8 @@ public boolean isArray() * the found declarations support the array property, otherwise it would be * enough that one of the declarations shows array structure. * @see #isArray() - * @see #isRecord() * @see #isRecord(boolean) + * @see #isEnum(boolean) * @_allDeclarations - whether all declarations must support the assumption * @return true if there is enough evidence of an array structure */ @@ -696,8 +798,10 @@ else if (!_allDeclarations && decl.isArray()) { /** * Indicates whether at least the first declaration states that the type * is a record (this may be in conflict with other declarations, though) - * @see #isRecord(boolean) * @return true if there is some evidence of an array structure + * @see #isRecord(boolean) + * @see #isArray() + * @see #isEnum() */ public boolean isRecord() { @@ -709,9 +813,10 @@ public boolean isRecord() * _allDeclarations is true then the result will only be true if all of * the found declarations support the record property, otherwise it would be * enough that one of the declarations shows array structure. - * @see #isArray() * @see #isRecord() * @see #isArray(boolean) + * @see #isArray(boolean) + * @see #isEnum(boolean) * @_allDeclarations - whether all declarations must support the assumption * @return true if there is enough evidence of an array structure */ @@ -728,6 +833,43 @@ else if (!_allDeclarations && decl.isRecord()) { return !_allDeclarations; } + /** + * Indicates whether at least the first declaration states that the type + * is an enumerator type (this may be in conflict with other declarations, though) + * @return true if there is some evidence of an enumeration + * @see #isEnum(boolean) + * @see #isArray() + * @see #isRecord() + */ + public boolean isEnum() + { + return !this.declarations.isEmpty() && this.declarations.element().isEnum(); + } + + /** + * Indicates whether there is some evidence for an enumeration type. If + * _allDeclarations is true then the result will only be true if all of + * the found declarations support the enum property, otherwise it would be + * enough that one of the declarations shows enumeration characteristics. + * @see #isEnum() + * @see #isArray(boolean) + * @see #isRecord(boolean) + * @_allDeclarations - whether all declarations must support the assumption + * @return true if there is enough evidence of an array structure + */ + public boolean isEnum(boolean _allDeclarations) + { + for (VarDeclaration decl: this.declarations) { + if (_allDeclarations && !decl.isEnum()) { + return false; + } + else if (!_allDeclarations && decl.isEnum()) { + return true; + } + } + return !_allDeclarations; + } + /** * Indicates whether this type entry refers to a named type definition * @return true if this has a type name. diff --git a/src/lu/fisch/structorizer/executor/Control.java b/src/lu/fisch/structorizer/executor/Control.java index 0a375834..ddae4970 100644 --- a/src/lu/fisch/structorizer/executor/Control.java +++ b/src/lu/fisch/structorizer/executor/Control.java @@ -66,6 +66,10 @@ * Kay Gürtzig 2017-10-31 Enh. #439: Internal class ValueEditor outsourced as ValuePresenter * Kay Gürtzig 2018-12-03 Bugfix #641: Display of updated variable values forced * Kay Gürtzig 2018-12-16 Issue #644: New message msgInitializerAsArgument + * Kay Gürtzig 2019-11-17 Enh. #739: New error message for defective enum type definitions + * Kay Gürtzig 2019-11-21 Enh. #739: Mnemonic display and ComboBox editing for enumerator values + * Editability check bug fixed in the table model fixed + * Kay Gürtzig 2019-11-25 Enh. #739: Protection against pending EnumeratorCellEditor on stop * ****************************************************************************************************** * @@ -145,6 +149,15 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole if (value instanceof JButton) { return (JButton)value; } + // START KGU#542 2019-11-21: Enh. #739 combobox for declared enumerator variables + else if (value instanceof JComboBox) { + Object item = ((JComboBox)value).getSelectedItem(); + if (item instanceof String) { + setText((String)item); + } + return this; + } + // END KGU#542 2019-11-21 // END KGU#443 2017-10-16 Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); DefaultTableModel model = (DefaultTableModel) table.getModel(); @@ -361,7 +374,7 @@ public boolean isCellEditable(int row, int column){ return true; // Pulldown button always enabled if there is one } else if (column > 1) { - String name = (String)this.getValueAt(row, column); + String name = (String)this.getValueAt(row, 0); return !Executor.getInstance().isConstant(name); } return false; @@ -374,6 +387,9 @@ else if (column > 1) { tblVar.getColumnModel().getColumn(1).setCellEditor(new PulldownButtonCellEditor()); tblVar.getColumnModel().getColumn(1).setMaxWidth(pulldownWidth); tblVar.getColumnModel().getColumn(1).setPreferredWidth(pulldownWidth); + // START KGU#542 2019-11-21: Enh. #739 - There may be comboboxes for enumerator variables + tblVar.getColumnModel().getColumn(2).setCellEditor(new EnumeratorCellEditor()); + // END KGU#542 2019-11-21 tblVar.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); // END KGU#443 2017-10-16 jScrollPane1.setViewportView(tblVar); @@ -606,6 +622,12 @@ private void btnStopActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:e chkCollectRuntimeData.setEnabled(true); cbRunDataDisplay.setEnabled(chkCollectRuntimeData.isSelected()); // END KGU#117 2016-03-06 + // START KGU#542 2019-11-25: Enh. #739 - We must ensure clean cell editor status on stop + if (activeEnumEditor != null) { + activeEnumEditor.stopCellEditing(); + activeEnumEditor = null; + } + // END KGU#542 2019-11-25 this.setVisible(false); } @@ -852,41 +874,28 @@ public void updateVars(Vector vars) // START KGU#443 2017-10-16: Enh. #439 - new pulldown buttons near compound values //tm.setValueAt(vars.get(i).get(0), i, 0); //tm.setValueAt(vars.get(i).get(1), i, 1); - JButton pulldown = null; - String name = vars.get(i)[0]; - String value = vars.get(i)[1]; - if (value.endsWith("}")) { - pulldown = new JButton(); - pulldown.setName(name); - pulldown.setIcon(pulldownIcon); - pulldown.addActionListener(this.pulldownActionListener); + Object[] rowData = makeVarListRow(vars.get(i), pulldownIcon); + for (int j = 0; j < rowData.length; j++) { + tm.setValueAt(rowData[j], i, j); } - tm.setValueAt(name, i, 0); - tm.setValueAt(pulldown, i, 1); - tm.setValueAt(value, i, 2); // END KGU#443 2017-10-16 } // Add additional rows for (int i = nRows; i < vars.size(); i++) { // START KGU#443 2017-10-16: Enh. #439 - new pulldown buttons near compound values //tm.addRow(vars.get(i)); - JButton pulldown = null; - String name = vars.get(i)[0]; - String value = vars.get(i)[1]; - if (value.endsWith("}")) { - pulldown = new JButton(); - pulldown.setName(name); - pulldown.setIcon(pulldownIcon); - pulldown.addActionListener(this.pulldownActionListener); - } - Object[] rowData = {name, pulldown, value}; - tm.addRow(rowData); + tm.addRow(makeVarListRow(vars.get(i), pulldownIcon)); // END KGU#443 2017-10-16 } // END KGU#274 2016-10-08 // START KGU#443 2017-10-16: Enh. #439 - Reserve the maximum space for last column if (vars.size() > 0) { - ValuePresenter.optimizeColumnWidth(tblVar, 0); + try { + ValuePresenter.optimizeColumnWidth(tblVar, 0); + } + catch (ArrayIndexOutOfBoundsException ex) { + // Just ignore it - it is caused by races. + } } // END KGU#443 2017-10-16 // START KGU#608 2018-12-03: Bugfix #641 - Sometimes the table didn't show the updated content @@ -894,6 +903,30 @@ public void updateVars(Vector vars) // ENDKGU#608 2018-12-03 } + /** + * @param varEntry - String array containing the variable name and a value string + * @param pulldownIcon - the icon to be used for a pull-down button + * @return an Object array representing teh prepared row for the variable display + */ + private Object[] makeVarListRow(String[] varEntry, ImageIcon pulldownIcon) { + JButton pulldown = null; + String name = varEntry[0]; + Object value = varEntry[1]; + if (varEntry[1].endsWith("}")) { + pulldown = new JButton(); + pulldown.setName(name); + pulldown.setIcon(pulldownIcon); + pulldown.addActionListener(this.pulldownActionListener); + } + else if (Executor.getInstance().isEnumerator(name) && !Executor.getInstance().isConstant(name)) { + StringList enumNames = Executor.getInstance().getEnumeratorValuesFor(name); + JComboBox cbEnum = new JComboBox(enumNames.toArray()); + cbEnum.setSelectedIndex(enumNames.indexOf(varEntry[1])); + value = cbEnum; + } + return new Object[]{name, pulldown, value}; + } + // START KGU#2 (#9) 2015-11-14: Update method for subroutine level display public void updateCallLevel(int level) { @@ -932,6 +965,9 @@ public void updateCallLevel(int level) /** Normative visibility for play and step button (to be restored when cell editor is released) */ private boolean startButtonsEnabled = true; // END KGU#442 2017-10-14 + // START KGU#542 2019-11-25: Enh. #739 - We must ensure clean cell editor status on stop + private AbstractCellEditor activeEnumEditor = null; + // END KGU#542 2019-11-25 // START KGU#443 2017-10-16: Enh. #439 private AbstractCellEditor activeBtnEditor = null; private java.awt.event.ActionListener pulldownActionListener = new java.awt.event.ActionListener(){ @@ -1078,6 +1114,9 @@ public void actionPerformed(ActionEvent evt) { public static final LangTextHolder msgErrorInSubroutine = new LangTextHolder("Caught error on executing «%1» at level %2:\n\t%3!"); public static final LangTextHolder msgThrown = new LangTextHolder("Exception thrown in «%1» at level %2: %3"); // END KGU#686 2019-03-17 + // START KGU#452 2019-11-17: Enh. #739 + public static final LangTextHolder msgInvalidEnumDefinition = new LangTextHolder("Invalid enumeration type definition «%»!"); + // END KGU#452 2019-11-17 // START KGU#68 2015-11-06: Register variable value editing events private final ConcurrentMap varUpdates = new ConcurrentHashMap(); @@ -1098,6 +1137,11 @@ public void propertyChange(PropertyChangeEvent pcEv) { if (cellEditor instanceof PulldownButtonCellEditor) { activeBtnEditor = (PulldownButtonCellEditor)cellEditor; } + // START KGU#542 2019-11-25: Enh. #739 - We must ensure clean cell editor status on stop + else if (cellEditor instanceof EnumeratorCellEditor) { + activeEnumEditor = (EnumeratorCellEditor)cellEditor; + } + // END KGU#542 2019-11-25p btnPlay.setEnabled(false); btnStep.setEnabled(false); if (startButtonsEnabled) { @@ -1115,6 +1159,14 @@ public void propertyChange(PropertyChangeEvent pcEv) { // END KGU#443 2017-10-16 if (val != null) { + // START KGU#542 2019-11-21: Enh. #739 - support enumerator variables + if (val instanceof JComboBox) { + val = ((JComboBox)val).getSelectedItem(); + // START KGU#542 2019-11-25: Enh. #739 - We must ensure clean cell editor status on stop + activeEnumEditor = null; + // END KGU#542 2019-11-25p + } + // END KGU#542 2019-11-21 varUpdates.put((String)tm.getValueAt(rowNr, 0), val); //System.out.println(tm.getValueAt(rowNr, 0).toString() + " <- " + val.toString()); } diff --git a/src/lu/fisch/structorizer/executor/EnumeratorCellEditor.java b/src/lu/fisch/structorizer/executor/EnumeratorCellEditor.java new file mode 100644 index 00000000..24037179 --- /dev/null +++ b/src/lu/fisch/structorizer/executor/EnumeratorCellEditor.java @@ -0,0 +1,104 @@ +/* + Structorizer + A little tool which you can use to create Nassi-Shneiderman Diagrams (NSD) + + Copyright (C) 2009 Bob Fisch + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +package lu.fisch.structorizer.executor; + +/****************************************************************************************************** + * + * Author: Kay Gürtzig + * + * Description: Cell editor class for JTable cells that may contain a String or a ComboBox. + * + ****************************************************************************************************** + * + * Revision List + * + * Author Date Description + * ------ ---- ----------- + * Kay Gürtzig 2019-11-21 First Issue (for enh. #739) + * + ****************************************************************************************************** + * + * Comment: + * + * + ******************************************************************************************************/// + +import java.awt.Component; + +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JTable; +import javax.swing.JTextField; + +/** + * Specific table cell editor for the value column in the variable display, capable + * of handling both JComboBoxes for enumerator variables and ordinary strings + * @author Kay Gürtzig + */ +@SuppressWarnings("serial") +public class EnumeratorCellEditor extends DefaultCellEditor { + + private JComboBox combo = null; + + /** + * @param textField + */ + public EnumeratorCellEditor() { + super(new JTextField()); + // TODO Auto-generated constructor stub + } + + /** + * @param comboBox + */ + public EnumeratorCellEditor(JComboBox comboBox) { + super(comboBox); + // TODO Auto-generated constructor stub + } + + @Override + public Object getCellEditorValue() { + if (this.combo != null) { + return this.combo; + } + return super.getCellEditorValue(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, + boolean isSelected, int row, int column) { + if (value instanceof JComboBox) { + this.combo = (JComboBox)value; + + if (isSelected) { + combo.setBackground(table.getSelectionBackground()); + } else { + combo.setBackground(table.getSelectionForeground()); + } + + return combo; + } + else { + this.combo = null; + return super.getTableCellEditorComponent(table, value, isSelected, row, column); + } + } + +} diff --git a/src/lu/fisch/structorizer/executor/Executor.java b/src/lu/fisch/structorizer/executor/Executor.java index 7d066948..6e10d3ac 100644 --- a/src/lu/fisch/structorizer/executor/Executor.java +++ b/src/lu/fisch/structorizer/executor/Executor.java @@ -184,6 +184,9 @@ * Kay Gürtzig 2019-10-15 Issue #763 - precautions against collateral effects of widened save check. * Kay Gürtzig 2019-11-08 Bugfix #769 - CASE selector list splitting was too simple for string literals * Kay Gürtzig 2019-11-09 Bugfix #771 - Unhandled errors deep from the interpreter + * Kay Gürtzig 2019-11-17 Enh. #739 - Support for enum type definitions + * Kay Gürtzig 2019-11-20/21 Enh. #739 - Several fixes and improvements for enh. #739 (enum types) + * Kay Gürtzig 2019-11-28 Bugfix #773: component access within index expressions caused trouble in some cases * ****************************************************************************************************** * @@ -313,7 +316,6 @@ import java.awt.event.WindowListener; import java.io.Closeable; import java.io.IOException; -import java.lang.Thread.UncaughtExceptionHandler; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -3367,6 +3369,7 @@ private String setVar(String target, Object content) throws EvalError * @see #setVarRaw(String, Object) * @see #setVar(String, Object) */ + @SuppressWarnings("unchecked") private String setVar(String target, Object content, int ignoreLoopStackLevel) throws EvalError // END KGU#307 2016-12-12 { @@ -3473,8 +3476,11 @@ else if (tokens.indexOf(".") == 1 || tokens.get(nTokens-1).equals("]")) { else { target = tokens.get(posLBrack-1); if (posLBrack == 1) { - indexStr = tokens.concatenate(" "); - // START KGU#490 2018-02-08: Bugfix #503 - we must apply string comparison conversion after decomposition# + // START KGU#773 2019-11-28: Bugfix #786 - To insert spaces wasn't helpful + //indexStr = tokens.concatenate(" "); + indexStr = tokens.concatenate(null); + // END KGU#773 2019-11-28 + // START KGU#490 2018-02-08: Bugfix #503 - we must apply string comparison conversion after decomposition // A string comparison in the index string may be unlikely but not impossible indexStr = this.convertStringComparison(indexStr); // END KGU#490 2018-02-08 @@ -3600,7 +3606,7 @@ else if (isConstant && content instanceof HashMap) { // KGU#432: The variable had been declared as array but not initialized - so be generous here objectArray = new ArrayList(); } - else if (targetObject instanceof ArrayList) { + else if (targetObject instanceof ArrayList) { objectArray = (ArrayList)targetObject; oldSize = objectArray.size(); } @@ -3918,6 +3924,23 @@ private void updateVariableDisplay() throws EvalError //myVar.add(this.interpreter.get(this.variables.get(i))); Object val = context.interpreter.get(varName); String valStr = prepareValueForDisplay(val, context.dynTypeMap); + // START KGU#542 2019-11-20: Enh. #739 - support enumeration types + TypeMapEntry varType = context.dynTypeMap.get(varName); + if (varType != null && varType.isEnum() && val instanceof Integer) { + int testVal = ((Integer)val).intValue(); + String enumStr = decodeEnumValue(testVal, varType); + if (enumStr != null) { + if (enumStr.equals(varName)) { + // This is the enumerator itself (a constant), so append the type name + valStr += " (" + varType.typeName + ")"; + } + else { + // For variables just holding the enumarator value, just show the name instead + valStr = enumStr; + } + } + } + // END KGU#542 2019-11-20 // END KGU#67 2015-11-08 vars.add(new String[]{varName, valStr}); } @@ -3938,11 +3961,10 @@ protected static String prepareValueForDisplay(Object val, HashMap) + if (val instanceof ArrayList) { valStr = "{"; - @SuppressWarnings("unchecked") - ArrayList valArray = (ArrayList)val; + ArrayList valArray = (ArrayList)val; for (int j = 0; j < valArray.size(); j++) { String elementStr = prepareValueForDisplay(valArray.get(j), typeMap); @@ -3956,8 +3978,7 @@ protected static String prepareValueForDisplay(Object val, HashMap hmVal = (HashMap)val; + HashMap hmVal = (HashMap)val; String typeName = String.valueOf(hmVal.get("§TYPENAME§")); valStr = typeName + "{"; // START KGU#526 2018-08-01: Enh. #423 - Try to preserve component order @@ -3973,12 +3994,14 @@ protected static String prepareValueForDisplay(Object val, HashMap entry: hmVal.entrySet()) + for (Entry entry: hmVal.entrySet()) { - String key = entry.getKey(); - if (!key.startsWith("§")) { - String elementStr = prepareValueForDisplay(entry.getValue(), typeMap); - valStr += ((j++ > 0) ? ", " : "") + key + ": " + elementStr; + if (entry.getKey() instanceof String) { + String key = (String)entry.getKey(); + if (!key.startsWith("§")) { + String elementStr = prepareValueForDisplay(entry.getValue(), typeMap); + valStr += ((j++ > 0) ? ", " : "") + key + ": " + elementStr; + } } } // START KGU#526 2018-08-01: Enh. #423 (continuation) @@ -4025,6 +4048,7 @@ public StringList adoptVarChanges(HashMap newValues) { String varName = entry.getKey(); try { + TypeMapEntry type = context.dynTypeMap.get(varName); Object oldValue = context.interpreter.get(varName); Object newValue = entry.getValue(); // START KGU#443 2017-10-29: Issue #439 Precaution against unnecessary value overwriting @@ -4089,12 +4113,11 @@ public StringList adoptVarChanges(HashMap newValues) // } } // START KGU#388 2017-10-08: Enh. #423 - else if (context.dynTypeMap.containsKey(varName) && context.dynTypeMap.get(varName).isRecord()) { + else if (type != null && type.isRecord()) { // START KGU#439 2017-10-13: Issue #436 We must not break references //context.interpreter.set(varName, evaluateExpression((String)newValue, true)); Object newObject = evaluateExpression((String)newValue, true, false); if (oldValue instanceof HashMap && newObject instanceof HashMap) { - TypeMapEntry type = context.dynTypeMap.get(varName); for (String key: type.getComponentInfo(true).keySet()) { if (!key.startsWith("§")) { if (((HashMap)newObject).containsKey(key)) { @@ -4111,6 +4134,17 @@ else if (oldValue == null) { } // END KGU#439 2017-10-13 } + // START KGU#542 2019-11-21: Enh. #739 - support enum types + else if (type != null && type.isEnum() && context.constants.containsKey(newValue)) { + Object constVal = context.constants.get(newValue); + if (constVal instanceof Integer && newValue.equals(this.decodeEnumValue((Integer)constVal, type))) { + context.interpreter.set(varName, constVal); + } + else { + setVarRaw(varName, (String)newValue); + } + } + // END KGU#542 2019-11-21 else { setVarRaw(varName, (String)newValue); @@ -4128,21 +4162,67 @@ else if (oldValue == null) { } // END KGU#68 2015-11-06 + // START KGU#542 2019-11-21: Enh. #739 Support for enumeration types + private String decodeEnumValue(int testVal, TypeMapEntry varType) { + int itemVal = 0; + StringList enumInfo = varType.getEnumerationInfo(); + for (int j = 0; j < enumInfo.count(); j++) { + String[] enumItem = enumInfo.get(j).split("\\s*=\\s*", 2); + if (enumItem.length > 1) { + try { + Object e1 = context.interpreter.eval(enumItem[1]); + if (e1 instanceof Integer && (Integer)e1 >= 0) { + itemVal = ((Integer)e1).intValue(); + } + } + catch (EvalError ex) {} + } + if (testVal == itemVal) { + return enumItem[0]; + } + itemVal++; + } + return null; + } + // END KGU#542 2019-11-21 + // START KGU#375 2017-03-30: Auxiliary callback for Control public boolean isConstant(String varName) { return context.constants.containsKey(varName.trim()); } // END KGU#375 2017-03-30 + + // START KGU#542 2019-11-21: Enh. #739 support for enumerator types + public boolean isEnumerator(String varName) + { + TypeMapEntry type = context.dynTypeMap.get(varName); + return type != null && type.isEnum(); + } + + public StringList getEnumeratorValuesFor(String varName) + { + TypeMapEntry type = context.dynTypeMap.get(varName); + if (type == null || !type.isEnum()) { + return null; + } + StringList names = type.getEnumerationInfo(); + for (int i = 0; i < names.count(); i++) { + int posEqu = names.get(i).indexOf('='); + if (posEqu >= 0) { + names.set(i, names.get(i).substring(0, posEqu).trim()); + } + } + return names; + } + // END KGU#542 2019-11-21 public void start(boolean useSteps) { paus = useSteps; step = useSteps; stop = false; - // START KGU#384 2017-04-22: execution context redesign - no longer an attribute - //this.variables = new StringList(); - // END KGU#384 2017-04-22 + control.updateVars(new Vector()); running = true; @@ -4184,18 +4264,6 @@ private String step(Element element) // END KGU#277 2016-10-13 element.executed = true; - // START KGU#276 2016-10-09: Issue #269: Now done in checkBreakpoint() -// if (delay != 0 || step) -// { -// diagram.redraw(); -// } -// if (step) { -// diagram.redraw(element); // Doesn't work properly... -// } -// else if (delay != 0) { -// diagram.redraw(); -// } - // END KGU#276 2016-10-09 // START KGU#143 2016-01-21: Bugfix #114 - make sure no compromising editing is done diagram.doButtons(); // END KGU#143 2016-01-21 @@ -4305,28 +4373,9 @@ private String stepRoot(Root element) element.waited = true; // START KGU#117 2016-03-07: Enh. #77 - consistent subqueue handling -// String trouble = new String(); -// int i = 0; -// // START KGU#77 2015-11-11: Leave if a return statement has been executed -// //while ((i < element.children.children.size()) -// // && trouble.equals("") && (stop == false)) -// while ((i < element.children.getSize()) -// && trouble.equals("") && (stop == false) && !returned) -// // END KGU#77 2015-11-11 -// { -// trouble = step(element.children.getElement(i)); -// i++; -// } String trouble = stepSubqueue(element.children, false); // END KGU#117 2016-03-07 - // START KGU#148 2016-01-29: Moved to execute -// delay(); -// if (trouble.equals("")) -// { -// element.clearExecutionStatus(); -// } - // END KGU#148 2016-01-29 return trouble; } @@ -4365,12 +4414,6 @@ private String stepInstruction(Instruction element) // START KGU#508 2018-03-19: Bugfix #525 operation count for all non-typedefs boolean isTypeDef = false; // END KGU#508 2018-03-19 - // START KGU#271: 2016-10-06: Bugfix #269 - this was mis-placed here and had to go to the loop body end -// if (i > 0) -// { -// delay(); -// } - // END KGU#271 2016-10-06 // START KGU#490 2018-02-07: Bugfix #503 - we should first rule out input, output instructions, and JUMPs //if (!Instruction.isTypeDefinition(cmd, context.dynTypeMap)) { @@ -4418,40 +4461,10 @@ else if (cmd.matches( // START KGU#377 2017-03-30: Bugfix //if (cmd.indexOf("<-") >= 0) if (Element.splitLexically(cmd, true).contains("<-")) - // END KGU#377 2017-03-30: Bugfix + // END KGU#377 2017-03-30: Bugfix { trouble = tryAssignment(cmd, element, i); } - // input - // START KGU#490 2018-02-07: Bugfix #503 - we should first rule out input, output instructions, and JUMPs - //// START KGU#65 2015-11-04: Input keyword should only trigger this if positioned at line start - ////else if (cmd.indexOf(CodeParser.input) >= 0) - //else if (cmd.matches( - // this.getKeywordPattern(CodeParser.getKeyword("input")) + "([\\W].*|$)")) - // // END KGU#65 2015-11-04 - //{ - // trouble = tryInput(cmd); - //} - //// output - // START KGU#65 2015-11-04: Output keyword should only trigger this if positioned at line start - //else if (cmd.indexOf(CodeParser.output) >= 0) - //else if (cmd.matches( - // this.getKeywordPattern(CodeParser.getKeyword("output")) + "([\\W].*|$)")) - // // END KGU#65 2015-11-04 - //{ - // trouble = tryOutput(cmd); - //} - //// return statement - //// START KGU 2015-11-28: The "return" keyword ought to be the first word of the instruction, - //// comparison should not be case-sensitive while CodeParser.preReturn isn't fully configurable, - //// but a separator would be fine... - ////else if (cmd.indexOf("return") >= 0) - //else if (cmd.matches( - // this.getKeywordPattern(CodeParser.getKeywordOrDefault("preReturn", "return")) + "([\\W].*|$)")) - // // END KGU 2015-11-11 - //{ - // trouble = tryReturn(cmd.trim()); - //} // START KGU#332 2017-01-17/19: Enh. #335 - tolerate a Pascal variable declaration else if (cmd.matches("^var.*:.*")) { // START KGU#388 2017-09-14: Enh. #423 @@ -4479,20 +4492,45 @@ else if (cmd.matches("^dim.* as .*")) { // END KGU#490 2018-02-08 trouble = trySubroutine(cmd, element); } - // START KGU#508 2018-03-19: Bugfix #525 - this has to be done for all non-typedefs - //// START KGU#156 2016-03-11: Enh. #124 - //element.addToExecTotalCount(1, true); // For the instruction line - ////END KGU#156 2016-03-11 - // END KGU#508 2018-03-19 // START KGU#388 2017-09-13: Enh. #423 } else { // START KGU#508 2018-03-19: Bugfix #525 operation count for non-typedefs + // We don't increment the total execution count here - this is regarded as a non-operation isTypeDef = true; // END KGU#508 2018-03-19 element.updateTypeMapFromLine(this.context.dynTypeMap, cmd, i); - // We don't increment the total execution count here - this is regarded as a non-operation + // START KGU#542 2019-11-17: Enh. #739 - In case of an enum type definition we have to assign the constants + String typeDescr = cmd.substring(cmd.indexOf('=')+1).trim(); + if (TypeMapEntry.MATCHER_ENUM.reset(typeDescr).matches()) { + isTypeDef = false; // Is to be counted as an ordinary instruction (costs even more) + HashMap enumItems = context.root.extractEnumerationConstants(cmd); + if (enumItems == null) { + trouble = Control.msgInvalidEnumDefinition.getText().replace("%", typeDescr); + } + else { + for (Entry enumItem: enumItems.entrySet()) { + String constName = enumItem.getKey(); + // This is the prefixed value + String enumValue = enumItem.getValue(); + // Check whether the constant may be set or confirmed + String oldVal = context.root.constants.put(constName, enumValue); + if (oldVal != null && !enumValue.equals(oldVal) || context.constants.containsKey(constName)) { + // There had been a differing value before + trouble = control.msgConstantRedefinition.getText().replace("%", constName); + break; + } + else { + // This is the pure value (ought to be an integral literal) + Object trueValue = context.interpreter.eval(context.root.getConstValueString(constName)); + // Now establish the value in the interpreter and the variable display + setVar("const " + constName, trueValue); + } + } + } + } + // END KGU#542 2019-11-17 } // END KGU#388 2017-09-13 // START KGU#156/KGU#508 2018-03-19: Enh. #124, bugfix #525 - this has to be done for all non-typedefs @@ -4551,7 +4589,7 @@ else if (cmd.matches("^dim.* as .*")) { // END KGU#569 2018-08-06 } i++; - } + } // while ((i < sl.count()) && trouble.equals("") ...) if (trouble.equals("")) { element.executed = false; @@ -4894,7 +4932,7 @@ private String evaluateDiagramControllerFunctions(String expression) throws Eval // START KGU 2015-11-11: Equivalent decomposition of method stepInstruction /** - * Submethod of stepInstruction(Instruction element), handling an assignment. + * Submethod of {@link #stepInstruction(Instruction)}, handling an assignment. * Also updates the dynamic type map. * @param cmd - the (assignment) instruction line, may also contain declarative parts * @param instr - the Instruction element @@ -5015,52 +5053,6 @@ else if (Element.E_COLLECTRUNTIMEDATA) // END KGU#2 2015-10-17 // Now evaluate the expression // START KGU#426 2017-09-30: Enh. #48, #423, bugfix #429 we need this code e.g in tryReturn, too -// // FIXME: This should be recursive! -// // START KGU#100 2016-01-14: Enh. #84 - accept array assignments with syntax array <- {val1, val2, ..., valN} -// else if (expression.startsWith("{") && expression.endsWith("}")) -// { -// // FIXME: We might have to evaluate those element values in advance, which are initializers themselves... -// this.evaluateExpression("Object[] tmp20160114kgu = " + expression, false); -// value = context.interpreter.get("tmp20160114kgu"); -// context.interpreter.unset("tmp20160114kgu"); -// } -// // END KGU#100 2016-01-14 -// // START KGU#388 2017-09-13: Enh. #423 - accept record assignments with syntax recordVar <- typename{comp1: val1, comp2: val2, ..., compN: valN} -// else if (tokens.indexOf("{") == 1 && expression.endsWith("}") -// && (recordType = identifyRecordType(tokens.get(0), true)) != null) -// { -// this.evaluateExpression("HashMap tmp20170913kgu = new HashMap()", false); -// HashMap components = Element.splitRecordInitializer(expression); -// if (components == null || components.containsKey("§TAIL§")) { -// trouble = control.msgInvalidExpr.getText().replace("%1", expression); -// } -// else { -// components.remove("§TYPENAME§"); -// LinkedHashMap compDefs = recordType.getComponentInfo(false); -// for (Entry comp: components.entrySet()) { -// // FIXME: We might have to evaluate the component value in advance if it is an initializer itself... -// if (compDefs.containsKey(comp.getKey())) { -// context.interpreter.eval("tmp20170913kgu.put(\"" + comp.getKey() + "\", " + comp.getValue() + ");"); -// } -// else { -// trouble = control.msgInvalidComponent.getText().replace("%1", comp.getKey()).replace("%2", recordType.typeName); -// break; -// } -// } -// value = context.interpreter.get("tmp20170913kgu"); -// if (value instanceof HashMap) { -// ((HashMap)value).put("§TYPENAME§", recordType.typeName); -// } -// context.interpreter.unset("tmp20170913kgu"); -// } -// } -// // END KGU#388 2017-09-13 -// else -// { -// //cmd = cmd.replace("<-", "="); -// -// value = this.evaluateExpression(expression); -// } else { value = this.evaluateExpression(expression, true, false); @@ -5076,18 +5068,18 @@ else if (Element.E_COLLECTRUNTIMEDATA) //instr.updateTypeMapFromLine(context.dynTypeMap, cmd, lineNo); if (!leftSide.contains(".") && !leftSide.contains("[")) { TypeMapEntry oldEntry = null; - String target = Instruction.getAssignedVarname(Element.splitLexically(leftSide, true)) + ""; + String target = Instruction.getAssignedVarname(Element.splitLexically(leftSide, true), false) + ""; if (!context.dynTypeMap.containsKey(target) || !(oldEntry = context.dynTypeMap.get(target)).isDeclared) { String typeDescr = Instruction.identifyExprType(context.dynTypeMap, expression, true); if (oldEntry == null) { TypeMapEntry typeEntry = null; if (typeDescr != null && (typeEntry = context.dynTypeMap.get(":" + typeDescr)) == null) { - typeEntry = new TypeMapEntry(typeDescr, null, null, instr, lineNo, true, false, false); + typeEntry = new TypeMapEntry(typeDescr, null, null, instr, lineNo, true, false); } context.dynTypeMap.put(target, typeEntry); } else { - oldEntry.addDeclaration(typeDescr, instr, lineNo, true, false); + oldEntry.addDeclaration(typeDescr, instr, lineNo, true); } } } @@ -5110,7 +5102,12 @@ else if (trouble.isEmpty() && !stop) } - // Submethod of stepInstruction(Instruction element), handling an input instruction + /** + * Submethod of {@link #stepInstruction(Instruction)}, handling an input instruction + * @param cmd - the instruction line expressing an input operation + * @return a possible error string + * @throws EvalError + */ private String tryInput(String cmd) throws EvalError { String trouble = ""; @@ -5380,7 +5377,12 @@ private boolean showMultipleInputDialog(Container parent, String prompt, StringL } // END KGU#653 2019-02-14 - // Submethod of stepInstruction(Instruction element), handling an output instruction + /** + * Submethod of {@link #stepInstruction(Instruction)}, handling an output instruction + * @param cmd - the output instruction line + * @return a possible error string + * @throws EvalError + */ private String tryOutput(String cmd) throws EvalError { String trouble = ""; @@ -5486,7 +5488,7 @@ private String tryReturn(String cmd) throws EvalError String trouble = ""; String header = control.lbReturnedResult.getText(); String out = cmd.substring(CodeParser.getKeywordOrDefault("preReturn", "return").length()).trim(); - // START KGU#77 (#21) 2015-11-13: We out to allow an empty return + // START KGU#77 (#21) 2015-11-13: We ought to allow an empty return //Object n = interpreter.eval(out); //if (n == null) //{ @@ -5699,72 +5701,6 @@ else if (trouble.isEmpty()) } } } - // START KGU#376 2017-04-11: Enh. #389 - withdrawn 2017-07-01 -// else if (element instanceof Call && element.isImportCall()) { -// Root imp = null; -// String diagrName = ((Call)element).getSignatureString(); -// try { -// imp = this.findProgramWithName(diagrName); -// } catch (Exception ex) { -// return ex.getMessage(); // Ambiguous call! -// } -// // END KGU#317 2016-12-29 -// if (imp != null) -// { -// // START KGU#376 207-04-21: Enh. ä389 -// // Has this import already been executed -then just adopt the results -// if (this.importMap.containsKey(imp)) { -// ImportInfo impInfo = this.importMap.get(imp); -// this.copyInterpreterContents(impInfo.interpreter, context.interpreter, -// imp.variables, null, imp.constants.keySet(), false); -// // FIXME adopt the imported typedefs if any -// context.variables.addIfNew(impInfo.variableNames); -// for (String constName: imp.constants.keySet()) { -// if (!context.constants.containsKey(constName)) { -// context.constants.put(constName, impInfo.interpreter.get(constName)); -// } -// } -// // START KGU#117 2017-04-29: Enh. #77 -// if (Element.E_COLLECTRUNTIMEDATA) -// { -// element.simplyCovered = true; -// if (imp.isTestCovered(true)) { -// element.deeplyCovered = true; -// } -// } -// // END KGU#117 2017-04-29 -// try -// { -// updateVariableDisplay(); -// } -// catch (EvalError ex) {} -// } -// else { -// // END KGU#376 2017-04-21 -// executeCall(imp, null, (Call)element); -// // START KGU#117 2016-03-10: Enh. #77 -// if (Element.E_COLLECTRUNTIMEDATA) -// { -// element.simplyCovered = true; -// } -// // END KGU#117 2016-03-10 -// // START KGU#376 207-04-21: Enh. ä389 -// } -// context.importList.addIfNew(diagrName); -// // END KGU#376 2017-04-21 -// } -// else -// { -// // START KGU#197 2016-07-27: Now translatable message -// //trouble = "A subroutine diagram " + f.getName() + " (" + f.paramCount() + -// // " parameters) could not be found!\nConsider starting the Arranger and place needed subroutine diagrams there first."; -// trouble = control.msgNoProgDiagram.getText(). -// replace("%", diagrName); -// // END KGU#197 2016-07-27 -// } -// -// } - // END KGU#376 2017-04-11 else { // START KGU#197 2017-06-06: Now localizable //trouble = "<" + cmd + "> is not a correct function!"; @@ -6073,26 +6009,6 @@ private String stepWhile(Element element, boolean eternal) element.waited = true; // START KGU#117 2016-03-07: Enh. #77 - consistent subqueue handling -// int i = 0; -// Subqueue body; -// if (eternal) -// { -// body = ((Forever)element).q; -// } -// else -// { -// body = ((While) element).q; -// } -// // START KGU#77/KGU#78 2015-11-25: Leave if some kind of Jump statement has been executed -// //while ((i < body.children.size()) -// // && trouble.equals("") && (stop == false)) -// while ((i < body.getSize()) -// && trouble.equals("") && (stop == false) && !returned && leave == 0) -// // END KGU#77/KGU#78 2015-11-25 -// { -// trouble = step(body.getElement(i)); -// i++; -// } if (trouble.isEmpty()) { trouble = stepSubqueue(((ILoop)element).getBody(), true); @@ -6233,17 +6149,6 @@ private String stepRepeat(Repeat element) do { // START KGU#117 2016-03-07: Enh. #77 - consistent subqueue handling -// int i = 0; -// // START KGU#77/KGU#78 2015-11-25: Leave if some Jump statement has been executed -// //while ((i < element.q.children.size()) -// // && trouble.equals("") && (stop == false)) -// while ((i < element.q.getSize()) -// && trouble.equals("") && (stop == false) && !returned && leave == 0) -// // END KGU#77/KGU#78 2015-11-25 -// { -// trouble = step(element.q.getElement(i)); -// i++; -// } if (trouble.isEmpty()) { trouble = stepSubqueue(element.getBody(), true); @@ -6327,54 +6232,15 @@ private String stepFor(For element) // END KGU#307 2016-12-12 try { - // START KGU#3 2015-10-31: Now it's time for the new intrinsic mechanism -// String str = element.getText().getText(); -// -// String pas = "1"; -// if(str.contains(", pas =")) // FIXME: Ought to be replaced by a properly configurable string -// { -// String[] pieces = str.split(", pas ="); -// str=pieces[0]; -// pas = pieces[1].trim(); -// } -// // START KGU 2015-10-13: The above mechanism has/had several flaws: -// // 1. The parsing works only for the hard-coded french keyword (ought to be a preference). -// // 2. the while condition didn't work for negative pas values. -// // 3. the pas value was parsed again and again in every loop. -// // 4. It's certainly not consistent with code export -// // To solve 2 and 3 we provide the Integer conversion once in advance int sval = element.getStepConst(); - // END KGU#3 2015-10-31 - - // START KGU#3 2015-10-27: Now replaced by For-intrinsic mechanisms -// // cut off the start of the expression -// if (!CodeParser.preFor.equals("")) -// { -// str = BString.replace(str, CodeParser.preFor, ""); -// } -// // trim blanks -// str = str.trim(); -// // modify the later word -// if (!CodeParser.postFor.equals("")) -// { -// str = BString.replace(str, CodeParser.postFor, "<="); -// } -// // do other transformations -// str = CGenerator.transform(str); -// String counter = str.substring(0, str.indexOf("=")); String counter = element.getCounterVar(); - // END KGU#3 2015-10-27 - // complete // START KGU#307 2016-12-12: Issue #307 - prepare warnings on loop variable manipulations context.forLoopVars.add(counter); // END KGU#307 2016-12-12 - // START KGU#3 2015-10-27: Now replaced by For-intrinsic mechanisms -// String s = str.substring(str.indexOf("=") + 1, -// str.indexOf("<=")).trim(); String s = element.getStartValue(); - // END KGU#3 2015-10-27 + s = convert(s); // START KGU#417 2017-06-30: Enh. #424 - Turtleizer functions must be evaluated s = this.evaluateDiagramControllerFunctions(s); @@ -6405,10 +6271,7 @@ else if (n instanceof Double) ival = ((Double) n).intValue(); } - // START KGU#3 2015-10-27: Now replaced by For-intrinsic mechanisms -// s = str.substring(str.indexOf("<=") + 2, str.length()).trim(); s = element.getEndValue(); - // END KGU#3 2015-10-27 s = convert(s); // START KGU#417 2017-06-30: Enh. #424 - Turtleizer functions must be evaluated s = this.evaluateDiagramControllerFunctions(s); @@ -6459,17 +6322,6 @@ else if (n instanceof Double) // START KGU#117 2016-03-07: Enh. #77 - consistent subqueue handling -// int i = 0; -// // START KGU#77/KGU#78 2015-11-25: Leave if a return statement has been executed -// //while ((i < element.q.children.size()) -// // && trouble.equals("") && (stop == false)) -// while ((i < element.q.getSize()) -// && trouble.equals("") && (stop == false) && !returned && leave == 0) -// // END KGU#77/KGU#78 2015-11-25 -// { -// trouble = step(element.q.getElement(i)); -// i++; -// } if (trouble.isEmpty()) { trouble = stepSubqueue(element.getBody(), true); @@ -6493,14 +6345,6 @@ else if (n instanceof Double) element.waited = true; // START KGU 2015-10-13: The step value is now calculated in advance -// try -// { -// cw+=Integer.valueOf(pas); -// } -// catch(Exception e) -// { -// cw++; -// } cw += sval; // END KGU 2015-10-13 } @@ -6633,8 +6477,8 @@ private String stepForIn(For element) { valueList = (Object[]) value; } - else if (value instanceof ArrayList) { - valueList = ((ArrayList)value).toArray(); + else if (value instanceof ArrayList) { + valueList = ((ArrayList)value).toArray(); } // START KGU#429 2017-10-08 else if (value instanceof String) { @@ -6959,6 +6803,9 @@ protected Object evaluateExpression(String _expr, boolean _withInitializers, boo { Object value = null; StringList tokens = Element.splitLexically(_expr, true); + // START KGU#773 2019-11-28: Bugfix #786 Blanks are not tolerated by the susequent mechanisms like index evaluation + tokens.removeAll(" "); + // END KGU#773 2019-11-28 // START KGU#439 2017-10-13: Enh. #436 Arrays now represented by ArrayLists if (!_preserveBrackets) { if (tokens.indexOf(OBJECT_ARRAY, 0, true) == 0) { @@ -7004,7 +6851,10 @@ else if (tokens.get(1).equals("{") && (recordType = identifyRecordType(tokens.ge // with partially undone conversions. This should not noticeably slow down the evaluation in case // no error occurs. boolean error423 = false; - String expr = tokens.concatenate(); + // START KGU#773 2019-11-28: Bugfix #786 Since blanks have been eliminated now, we must be cautious on concatenation + //String expr = tokens.concatenate(); + String expr = tokens.concatenate(null); + // END KGU#773 2019-11-28 boolean messageAugmented = false; do { error423 = false; @@ -7164,7 +7014,7 @@ private Object evaluateRecordInitializer(String _expr, StringList tokens, TypeMa // this.evaluateExpression("HashMap tmp20170913kgu = new HashMap()", false); // START KGU#559 2018-07-20: Enh. #563 - simplified record initializers (smarter interpretation) //HashMap components = Element.splitRecordInitializer(tokens.concatenate(null)); - HashMap components = Element.splitRecordInitializer(tokens.concatenate(null), recordType); + HashMap components = Element.splitRecordInitializer(tokens.concatenate(null), recordType, false); // END KGU#559 2018-07-20 if (components == null || components.containsKey("§TAIL§")) { throw new EvalError(control.msgInvalidExpr.getText().replace("%1", _expr), null, null); @@ -7227,7 +7077,7 @@ private void waitForNext() // START KGU#33/KGU#34 2014-12-05 // Method tries to extract the index value from an expression formed like - // a array element access, i.e. "[]" + // an array element access, i.e. "[]" private int getIndexValue(String varname) throws EvalError { // START KGU#141 2016-01-16: Bugfix #112 diff --git a/src/lu/fisch/structorizer/executor/Function.java b/src/lu/fisch/structorizer/executor/Function.java index 8192badc..f995ea3b 100644 --- a/src/lu/fisch/structorizer/executor/Function.java +++ b/src/lu/fisch/structorizer/executor/Function.java @@ -404,8 +404,9 @@ public static boolean testIdentifier(String _str, String _alsoAllowedChars) // START KGU 2016-10-16: More informative self-description public String toString() { + String paramNames = this.parameters == null ? "" : this.parameters.concatenate(", "); return getClass().getSimpleName() + '@' + Integer.toHexString(hashCode()) + - ": " + this.getName() + "(" + this.parameters.concatenate(", ") + ")"; + ": " + this.getName() + "(" + paramNames + ")"; } // END KGU# 2016-10-16 diff --git a/src/lu/fisch/structorizer/generators/BASHGenerator.java b/src/lu/fisch/structorizer/generators/BASHGenerator.java index 569b6fd3..b3bb102a 100644 --- a/src/lu/fisch/structorizer/generators/BASHGenerator.java +++ b/src/lu/fisch/structorizer/generators/BASHGenerator.java @@ -81,6 +81,9 @@ * Kay Gürtzig 2019-09-27 Enh. #738: Support for code preview map on Root level * Kay Gürttig 2019-10-15 Bugfix #765: Private field typeMap had to be made protected * Kay Gürtzig 2019-11-08 Bugfix #769: Undercomplex selector list splitting in CASE generation mended + * Kay Gürtzig 2019-11-24 Bugfix #783 - Workaround for record initializers without known type + * Kay Gürtzig 2019-11-24 Bugfix #784 - Suppression of mere declarations and fix in transformExpression() + * Kay Gürtzig 2019-12-01 Enh. #739: Support for enum types, $() around calls removed, array decl subclassable * ****************************************************************************************************** * @@ -124,6 +127,7 @@ import java.util.HashMap; import java.util.Map.Entry; import java.util.regex.Matcher; +import java.util.regex.Pattern; import lu.fisch.structorizer.elements.Alternative; import lu.fisch.structorizer.elements.Call; @@ -258,6 +262,28 @@ protected TryCatchSupportLevel getTryCatchLevel() /************ Code Generation **************/ + protected static final Matcher VAR_ACCESS_MATCHER = Pattern.compile("[$]\\{[A-Za-z][A-Za-z0-9_]*\\}").matcher(""); + + // START KGU#542 2019-12-01: Enh. #739 enumeration type support - configuration for subclasses + /** @return the shell-specific declarator for enumeration constants (e.g. {@code "declare -ri "} for bash) */ + protected String getEnumDeclarator() + { + return "declare -ri "; + } + + /** @return the shell-specific declarator for array variables (e.g. {@code "declare -a "} for bash) */ + protected String getArrayDeclarator() + { + return "declare -a "; + } + + /** @return the shell-specific declarator for associative arrays (maps, e.g. {@code "declare -A "} for bash) */ + protected String getAssocDeclarator() + { + return "declare -A "; + } + // END KGU#542 2019-12-01 + // START KGU#753 2019-10-15: Bugfix #765 had to be made protected, since KSHGenerator must initialize it as well. //private HashMap typeMap = null; protected HashMap typeMap = null; @@ -336,13 +362,8 @@ protected boolean checkElementInformation(Element _ele) @Override protected String transformTokens(StringList tokens) { - // Trim the tokens at end (just for sure) - int pos0 = 0; - int posx = tokens.count(); - while (pos0 < posx && tokens.get(pos0).equals(" ")) { pos0++; } - while (pos0 < posx && tokens.get(posx-1).equals(" ")) { posx--; } - tokens.remove(posx, tokens.count()); - tokens.remove(0, pos0); + // Trim the tokens at both ends (just for sure) + tokens = tokens.trim(); // START KGU#129 2016-01-08: Bugfix #96 - variable name processing // We must of course identify variable names and prefix them with $ unless being an lvalue int posAsgnOpr = tokens.indexOf("<-"); @@ -393,19 +414,19 @@ else if (token0.equalsIgnoreCase("dim")) { int posBracket1 = tokens.indexOf("["); int posBracket2 = -1; if (posBracket1 >= 0 && posBracket1 < posAsgnOpr) posBracket2 = tokens.lastIndexOf("]", posAsgnOpr-1); - for (int i = 0; i < varNames.count(); i++) - { - String varName = varNames.get(i); - //System.out.println("Looking for " + varName + "..."); // FIXME (KGU): Remove after Test! - //_input = _input.replaceAll("(.*?[^\\$])" + varName + "([\\W$].*?)", "$1" + "\\$" + varName + "$2"); - // Transform the expression right of the assignment symbol - transformVariableAccess(varName, tokens, posAsgnOpr+1, tokens.count()); - // Transform the index expression on the left side of the assignment symbol - transformVariableAccess(varName, tokens, posBracket1+1, posBracket2+1); - } + for (int i = 0; i < varNames.count(); i++) + { + String varName = varNames.get(i); + //System.out.println("Looking for " + varName + "..."); // FIXME (KGU): Remove after Test! + //_input = _input.replaceAll("(.*?[^\\$])" + varName + "([\\W$].*?)", "$1" + "\\$" + varName + "$2"); + // Transform the expression right of the assignment symbol + transformVariableAccess(varName, tokens, posAsgnOpr+1, tokens.count()); + // Transform the index expression on the left side of the assignment symbol + transformVariableAccess(varName, tokens, posBracket1+1, posBracket2+1); + } // Position of the assignment operator may have changed now - posAsgnOpr = tokens.indexOf("<-"); + posAsgnOpr = tokens.indexOf("<-"); // END KGU#96 2016-01-08 // FIXME (KGU): Function calls, math expressions etc. will have to be put into brackets etc. pp. tokens.replaceAll("div", "/"); @@ -437,11 +458,8 @@ else if (tokens.count() > 0) } } } - // Trim the tokens at front - pos0 = 0; - posx = tokens.count(); - while (pos0 < posx && tokens.get(pos0).equals(" ")) { pos0++; } - tokens.remove(0, pos0); + // Trim the tokens (at front) + tokens = tokens.trim(); // Re-combine the rval expression to a string String expr = tokens.concatenate(); // If the expression is a function call, then convert it to shell syntax @@ -469,7 +487,11 @@ else if (tokens.count() > 0) //} expr = transformExpression(fct); // END KGU#405 2017-05-19 - if (posAsgnOpr > 0) + // START KGU 2019-12-01: An evaluation should not apply for subroutines! + //if (posAsgnOpr > 0) + if (posAsgnOpr > 0 && + (this.routinePool == null || this.routinePool.findRoutinesBySignature(fct.getName(), fct.paramCount(), null).isEmpty())) + // END KGU 2019-12-01 { // START KGU#390 2017-05-05: Issue #396 //expr = "`" + expr + "`"; @@ -477,9 +499,10 @@ else if (tokens.count() > 0) // END KGU#390 2017-05-05 } } + // FIXME (KGU 2019-12-01) this looks too simplistic else if (expr.startsWith("{") && expr.endsWith("}") && posAsgnOpr > 0) { - lval = "declare -a " + lval; + lval = this.getArrayDeclarator() + lval; StringList items = Element.splitExpressionList(expr.substring(1, expr.length()-1), ","); // START KGU#405 2017-05-19: Bugfix #237 - was too simple an analysis for (int i = 0; i < items.count(); i++) { @@ -493,8 +516,11 @@ else if (tokens.count() > 2 && Function.testIdentifier(tokens.get(0), null) && tokens.get(1).equals("{") && expr.endsWith("}") // START KGU#559 2018-07-20: Enh. # Try to fetch sufficient type info //&& (recordIni = Element.splitRecordInitializer(expr, null)) != null) { - && (recordIni = Element.splitRecordInitializer(expr, this.typeMap.get(":"+tokens.get(0)))) != null) { + && (recordIni = Element.splitRecordInitializer(expr, this.typeMap.get(":"+tokens.get(0)), false)) != null) { // END KGU#559 2018-07-20 + // START KGU#388 2019-11-28: Bugfix #423 - record initializations must not be separated from the declaration + lval = this.getArrayDeclarator() + lval; + // END KGU#388 2019-11-28 StringBuilder sb = new StringBuilder(15 * recordIni.size()); String sepa = "("; for (Entry entry: recordIni.entrySet()) { @@ -504,8 +530,15 @@ else if (tokens.count() > 2 && Function.testIdentifier(tokens.get(0), null) sepa = " "; } } - sb.append(")"); - expr = sb.toString(); + // START KGU#771 2019-11-24: Bugfix #783 - fallback for the case of missing struct info + //sb.append(")"); + //expr = sb.toString(); + // If the type info was available or didn't provide any content then leave expr as is + if (sb.length() > 0) { + sb.append(")"); + expr = sb.toString(); + } + // END KGU#771 2019-11-24 } // END KGU#388 2017-10-24 // The following is a very rough and vague heuristics to support arithmetic expressions @@ -554,14 +587,36 @@ protected String transformExpression(StringList exprTokens, boolean isAssigned) exprTokens.contains("*") || exprTokens.contains("/") || exprTokens.contains("%"); + // Avoid recursive enclosing in $(...) if (isArithm) { exprTokens.insert((isAssigned ? "$(( " : "(( "), 0); exprTokens.add(" ))"); } + // START KGU#772 2019-11-24: Bugfix #784 - avoid redundant enclosing with $(...) + //else if (isAssigned) { + // exprTokens.insert("$(", 0); + // exprTokens.add(")"); + //} else if (isAssigned) { - exprTokens.insert("$(", 0); - exprTokens.add(")"); + boolean isVarAccess = + exprTokens.count() == 4 && + exprTokens.get(0).equals("$") && + exprTokens.get(1).equals("{") && + this.varNames.contains(exprTokens.get(2)) && + exprTokens.get(3).equals("}") || + exprTokens.count() == 1 && + VAR_ACCESS_MATCHER.reset(exprTokens.get(0)).matches() && + this.varNames.contains(exprTokens.get(0).substring(2, exprTokens.get(0).length()-1)); + if (isVarAccess) { + exprTokens.insert("\"", 0); + exprTokens.add("\""); + } + else { + exprTokens.insert("$(", 0); + exprTokens.add(")"); + } } + // END KGU#772 2019-11-24 return exprTokens.concatenate(); } protected String transformExpression(String expr, boolean isAssigned) @@ -750,10 +805,10 @@ else if (intermed.matches("^" + Matcher.quoteReplacement(preExit) + "(\\W.*|$)") // END KGU#162 2016-03-31 - // START KGU#114 2015-12-22: Bugfix #71 - //return _input.trim(); - return intermed.trim(); - // END KGU#114 2015-12-22 + // START KGU#114 2015-12-22: Bugfix #71 + //return _input.trim(); + return intermed.trim(); + // END KGU#114 2015-12-22 } /* (non-Javadoc) @@ -802,11 +857,12 @@ protected void generateCode(Instruction _inst, String _indent) { continue; } // END KGU#653 2019-02-15 - // START KGU#388 2017-10-24: Enh. #423 ignore type definitions - if (Instruction.isTypeDefinition(line)) { + // START KGU#388/KGU#772 2017-10-24/2019-11-24: Enh. #423/bugfix #784 ignore type definitions and mere variable declarations + //if (Instruction.isTypeDefinition(line)) { + if (Instruction.isMereDeclaration(line)) { continue; } - // END KGU#388 2017-10-24 + // END KGU#388/KGU#772 2017-10-24/2019-11-24 String codeLine = transform(line); // START KGU#311 2017-01-05: Enh. #314: We should at least put some File API remarks if (this.usesFileAPI) { @@ -1177,7 +1233,7 @@ protected void generateCode(Call _call, String _indent) { // START KGU#277 2016-10-14: Enh. #270 boolean disabled = _call.isDisabled(); // END KGU#277 2016-10-14 - for(int i=0;i<_call.getText().count();i++) + for (int i = 0; i < _call.getText().count(); i++) { // START KGU#277 2016-10-14: Enh. #270 //code.add(_indent+transform(_call.getText().get(i))); @@ -1386,18 +1442,27 @@ public String generateCode(Root _root, String _indent) { appendComment("TODO: Check and revise the syntax of all expressions!", _indent); code.add(""); // END KGU#129 2016-01-08 + // START KGU#542 2019-12-01: Enh. #739 - support for enumeration types + for (Entry typeEntry: typeMap.entrySet()) { + TypeMapEntry type = typeEntry.getValue(); + if (typeEntry.getKey().startsWith(":") && type != null && type.isEnum()) { + appendEnumeratorDef(type, _indent); + } + } + // END KGU#542 2019-12-01 // START KGU#389 2017-10-23: Enh. #423 declare records as associative arrays + // FIXME: We should only do so if they won't get initialized for (int i = 0; i < varNames.count(); i++) { String varName = varNames.get(i); TypeMapEntry typeEntry = typeMap.get(varName); if (typeEntry != null && typeEntry.isRecord()) { - addCode("declare -A " + varName, _indent, false); + addCode(this.getAssocDeclarator() + varName, _indent, false); } } // END KGU#389 2017-10-23 generateCode(_root.children, indent); - if( ! _root.isProgram() ) { + if (_root.isSubroutine()) { code.add("}"); } @@ -1411,6 +1476,38 @@ public String generateCode(Root _root, String _indent) { return code.getText(); } + + // START KGU#542 2019-12-01: Enh. #739 support for enumeration types + /** + * Generates a shell equivalent for an enumeration type by declaring the + * respective set of read-only integer variables. + * @param _type - the {@link TpyeMapEntry} of the enumeration type + * @param _indent - the current indentation string + */ + protected void appendEnumeratorDef(TypeMapEntry _type, String _indent) { + StringList enumItems = _type.getEnumerationInfo(); + appendComment("START enumeration type " + _type.typeName, _indent); + // In vintage BASIC, we will just generate separate variable definitions + int offset = 0; + String lastVal = ""; + for (int i = 0; i < enumItems.count(); i++) { + String[] itemSpec = enumItems.get(i).split("=", 2); + if (itemSpec.length > 1) { + lastVal = itemSpec[1].trim(); + offset = 0; + try { + int code = Integer.parseUnsignedInt(lastVal); + lastVal = ""; + offset = code; + } + catch (NumberFormatException ex) {} + } + addCode(this.getEnumDeclarator() + itemSpec[0] + "=" + transform(lastVal) + (lastVal.isEmpty() ? "" : "+") + offset, _indent, false); + offset++; + } + appendComment("END enumeration type "+ _type.typeName, _indent); + } + // END KGU#542 2019-12-01 } diff --git a/src/lu/fisch/structorizer/generators/BasGenerator.java b/src/lu/fisch/structorizer/generators/BasGenerator.java index fa227cdd..e80ae704 100644 --- a/src/lu/fisch/structorizer/generators/BasGenerator.java +++ b/src/lu/fisch/structorizer/generators/BasGenerator.java @@ -57,12 +57,15 @@ * Kay Gürtzig 2017-02-27 Enh. #346: Formal adaptation * Kay Gürtzig 2017-03-15 Bugfix #382: FOR-IN loop value list items hadn't been transformed * Kay Gürtzig 2017-05-16 Enh. #372: Export of copyright information - * Kay Gürtzig 2017-11-02 Issue #447: Line continuation in Case elements supported + * Kay Gürtzig 2017-11-02 Issues #416, #447: Line continuation in Case elements supported * Kay Gürtzig 2019-03-08 Enh. #385: Support for parameter default values * Kay Gürtzig 2019-03-13 Enh. #696: All references to Arranger replaced by routinePool * Kay Gürtzig 2019-03-08 Enh. #385: Support for parameter default values * Kay Gürtzig 2019-03-18 Enh. #56: Export of Try blocks implemented * Kay Gürtzig 2019-03-28 Enh. #657: Retrieval for subroutines now with group filter + * Kay Gürtzig 2019-12-01 Bugfix #789 (function calls); keyword case modified for non-vintage BASIC, + * bugfix #790 line continuation according to #416 hadn't been considered, + * array initializers and record types hadn't been handled correctly * ****************************************************************************************************** * @@ -79,6 +82,10 @@ * ******************************************************************************************************/// +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + import lu.fisch.structorizer.elements.Alternative; import lu.fisch.structorizer.elements.Call; import lu.fisch.structorizer.elements.Case; @@ -93,6 +100,7 @@ import lu.fisch.structorizer.elements.Root; import lu.fisch.structorizer.elements.Subqueue; import lu.fisch.structorizer.elements.Try; +import lu.fisch.structorizer.elements.TypeMapEntry; import lu.fisch.structorizer.elements.While; import lu.fisch.structorizer.executor.Function; import lu.fisch.structorizer.generators.Generator.TryCatchSupportLevel; @@ -142,7 +150,7 @@ protected String[] getFileExtensions() @Override protected String commentSymbolLeft() { - return "REM"; + return transformKeyword("REM"); } // END KGU 2015-10-18 @@ -248,6 +256,26 @@ protected String getOutputReplacer() return "PRINT $1"; } + // START KGU 2019-12-01 - Use different case styles for Vintage BASIC and modern BASIC + private String transformKeyword(String keyword) + { + if (this.optionCodeLineNumbering()) { + keyword = keyword.toUpperCase(); + } + else { + String[] parts = keyword.split(" ", -2); + for (int i = 0; i < parts.length; i++) { + String part = parts[i]; + if (!part.isEmpty()) { + parts[i] = Character.toUpperCase(part.charAt(0)) + part.substring(1).toLowerCase(); + } + } + keyword = (new StringList(parts)).concatenate(" "); + } + return keyword; + } + // END KGU 2019-12-01 + // START KGU#93 2015-12-21: Bugfix #41/#68/#69 // /** // * Transforms assignments in the given intermediate-language code line. @@ -299,13 +327,18 @@ protected String transformTokens(StringList tokens) } } // END KGU#150 2016-04-04 + // START KGU 2019-12-01 In vintage BASIC there is no "const" + if (this.optionCodeLineNumbering()) { + tokens.removeAll("const"); + } + // END KGU 2019-12-01 if (tokens.contains("<-") && this.optionCodeLineNumbering()) { // Insert a "LET" keyword but ensure a separating blank between it and the variable name if (!tokens.get(0).equals(" ")) tokens.insert(" ", 0); - tokens.insert("LET", 0); + tokens.insert(transformKeyword("LET"), 0); } - // START KGU#100 2016-01-22: Enh #84 - Array initialisiation for Visual/modern BASIC + // START KGU#100 2016-01-22: Enh #84 - Array initialisation for Visual/modern BASIC if (!this.optionCodeLineNumbering()) { tokens.replaceAll("{", "Array("); @@ -336,29 +369,29 @@ protected String getLineNumber() return prefix; } - protected void placeJumpTarget(ILoop _loop, String _indent) - { - if (this.jumpTable.containsKey(_loop.getLoop())) - { - if (this.optionCodeLineNumbering()) - { - // Associate label number with line number of the following dummy comment - this.labelMap[this.jumpTable.get(_loop.getLoop()).intValue()] = this.lineNumber; - appendComment("Exit point from above loop.", _indent); - } - else - { - // START KGU#277 2016-10-13: Enh. #270 - //code.add(_indent + this.labelBaseName + this.jumpTable.get(_loop).toString() + ": " + - // this.commentSymbolLeft() + " Exit point from above loop."); - addCode(this.labelBaseName + this.jumpTable.get(_loop.getLoop()).toString() + ": " + - this.commentSymbolLeft() + " Exit point from above loop.", - _indent, _loop.isDisabled()); - // END KGU#277 2016-10-13 - } - } + protected void placeJumpTarget(ILoop _loop, String _indent) + { + if (this.jumpTable.containsKey(_loop.getLoop())) + { + if (this.optionCodeLineNumbering()) + { + // Associate label number with line number of the following dummy comment + this.labelMap[this.jumpTable.get(_loop.getLoop()).intValue()] = this.lineNumber; + appendComment("Exit point from above loop.", _indent); + } + else + { + // START KGU#277 2016-10-13: Enh. #270 + //code.add(_indent + this.labelBaseName + this.jumpTable.get(_loop).toString() + ": " + + // this.commentSymbolLeft() + " Exit point from above loop."); + addCode(this.labelBaseName + this.jumpTable.get(_loop.getLoop()).toString() + ": " + + this.commentSymbolLeft() + " Exit point from above loop.", + _indent, _loop.isDisabled()); + // END KGU#277 2016-10-13 + } + } - } + } // We need an overridden fundamental comment method here to be able to insert line numbers. /* (non-Javadoc) @@ -424,7 +457,7 @@ protected String transform(String _input) // START KGU#108 2015-12-19: Bugfix #51/Enh. #271: Cope with empty input if (interm.trim().equals("INPUT") || interm.endsWith(": INPUT")) { - interm = interm.replace("INPUT", "SLEEP"); // waits for key hit (according to https://en.wikibooks.org/wiki/BASIC_Programming/Beginning_BASIC/User_Input) + interm = interm.replace("INPUT", transformKeyword("SLEEP")); // waits for key hit (according to https://en.wikibooks.org/wiki/BASIC_Programming/Beginning_BASIC/User_Input) } // END KGU#108 2015-12-19 @@ -476,59 +509,77 @@ protected void generateCode(Instruction _inst, String _indent) // START KGU 2014-11-16 appendComment(_inst, _indent); // END KGU 2014-11-16 - for(int i=0; i<_inst.getText().count(); i++) + // START KGU#779 2019-12-01: Bugfix #790 (enh. #416) + //for(int i=0; i<_inst.getText().count(); i++) + Root root = Element.getRoot(_inst); + StringList lines = _inst.getUnbrokenText(); + for (int i = 0; i < lines.count(); i++) + // END KGU#779 2019-12-01 { + // START KGU#779 2019-12-01: Bugfix #790 (enh. #416) + String line = lines.get(i); + StringList tokens = Element.splitLexically(line, true); + Element.unifyOperators(tokens, false); + boolean isRecordInit = false; + // END KGU#779 2019-12-01 // START KGU#100 2016-01-22: Enh. #84 - resolve array initialisation boolean isArrayInit = false; - // START KGU#171 2016-03-31: Enh. #144 + // START KGU#171 2016-03-31: Enh. #144 / KGU#779 2019-12-01: bugfix #790 //if (this.optionBasicLineNumbering()) - if (!this.suppressTransformation && this.optionCodeLineNumbering()) - // END KGU#171 2016-03-31 + if (!this.suppressTransformation /*&& this.optionCodeLineNumbering()*/) + // END KGU#171 2016-03-31 / KGU#779 2019-12-01 { + // START KGU#779 2019-12-01 + if (Instruction.isTypeDefinition(line)) { + generateTypeDef(tokens, root, _indent, disabled); + continue; + } // The crux is: we don't know the index range! // So we'll invent an index base variable easy to be modified in code //code.add(_indent + transform(line) + ";"); - String uniline = Element.unifyOperators(_inst.getText().get(i)); - int asgnPos = uniline.indexOf("<-"); - if (asgnPos >= 0 && uniline.contains("{") && uniline.contains("}")) + int asgnPos = tokens.indexOf("<-"); + if (asgnPos >= 0) { - String varName = transform(uniline.substring(0, asgnPos).trim()); - String expr = uniline.substring(asgnPos+2).trim(); - isArrayInit = expr.startsWith("{") && expr.endsWith("}"); + StringList leftSide = tokens.subSequence(0, asgnPos); + leftSide.removeAll(" "); + String varName = Instruction.getAssignedVarname(leftSide, false); + StringList exprTokens = tokens.subSequence(asgnPos+1, tokens.count()).trim(); + isArrayInit = !exprTokens.isEmpty() && exprTokens.get(0).equals("{") && exprTokens.get(exprTokens.count()-1).equals("}"); + // START KGU#780 2019-12-01 - trouble with complicated left sides fixed + int posColon = leftSide.indexOf(":"); + int posAs = leftSide.indexOf("as", false); + if (posColon > 0) { + leftSide = leftSide.subSequence(0, posColon); + } + if (posAs > 0 && posAs < leftSide.count()) { + leftSide = leftSide.subSequence(0, posAs); + } + String target = leftSide.concatenate(null); + varName = transform(target.substring(target.indexOf(varName))); + // END KGU#780 2019-12-01 if (isArrayInit) { - StringList elements = Element.splitExpressionList( - expr.substring(1, expr.length()-1), ","); - // In order to be consistent with possible index access - // at other positions in code, we use the standard Java - // index range here (though in Pascal indexing usually - // starts with 1 but may vary widely). We solve the problem - // by providing a configurable start index variable - appendComment("TODO: Check indexBase value (automatically generated)", _indent); - // START KGU#277 2016-10-13: Enh. #270 - //code.add(this.getLineNumber() + _indent + "LET indexBase = 0"); - addCode("LET indexBase = 0", _indent, disabled); - // END KGU#277 2016-10-13 - for (int el = 0; el < elements.count(); el++) - { - // START KGU#277 2016-10-13: Enh. #270 - //code.add(this.getLineNumber() + _indent + "LET " + varName + - // "(indexBase + " + el + ") = " + - // transform(elements.get(el))); - addCode("LET " + varName + "(indexBase + " + el + ") = " + - transform(elements.get(el)), _indent, disabled); - // END KGU#277 2016-10-13 + generateArrayInit(varName, exprTokens, _indent, disabled); + } + StringList compList = null; + isRecordInit = !isArrayInit && exprTokens.count() > 2 && Function.testIdentifier(exprTokens.get(0), null) + && exprTokens.get(exprTokens.count()-1).equals("}") + && !(compList = exprTokens.subSequence(1, exprTokens.count()).trim()).isEmpty() + && compList.get(0).equals("{"); + if (isRecordInit) { + TypeMapEntry type = root.getTypeInfo(routinePool).get(":" + exprTokens.get(0)); + if (type != null && Function.testIdentifier(varName, null) && !this.wasDefHandled(root, varName, true)) { + addCode(transformKeyword("DIM ") + varName + transformKeyword(" AS ") + type.typeName, _indent, disabled); } + this.generateRecordInit(varName, exprTokens.concatenate(), _indent, disabled, type); } - } } - if (!isArrayInit) + if (!isArrayInit && !isRecordInit) { // END KGU#100 2016-01-22 // START KGU#277/KGU#284 2016-10-13/16: Enh. #270 + Enh. #274 //code.add(this.getLineNumber() + _indent + transform(_inst.getText().get(i))); - String line = _inst.getText().get(i); String codeLine = transform(line); if (Instruction.isTurtleizerMove(line)) { codeLine += " : " + this.commentSymbolLeft() + " color = " + _inst.getHexColor(); @@ -542,6 +593,150 @@ protected void generateCode(Instruction _inst, String _indent) } } + /** + * @param _targetVar + * @param _exprTokens + * @param _indent + * @param _disabled + */ + private void generateArrayInit(String _targetVar, StringList _exprTokens, String _indent, boolean _disabled) { + StringList elements = Element.splitExpressionList( + _exprTokens.concatenate(null, 1), ","); + if (this.optionCodeLineNumbering()) { + // In order to be consistent with possible index access + // at other positions in code, we use the standard Java + // index range here (though in Pascal indexing usually + // starts with 1 but may vary widely). We solve the problem + // by providing a configurable start index variable + appendComment("TODO: Check indexBase value (automatically generated)", _indent); + // START KGU#277 2016-10-13: Enh. #270 + //code.add(this.getLineNumber() + _indent + "LET indexBase = 0"); + addCode(transformKeyword("LET") + " indexBase = 0", _indent, _disabled); + // END KGU#277 2016-10-13 + for (int el = 0; el < elements.count(); el++) + { + // START KGU#277 2016-10-13: Enh. #270 + //code.add(this.getLineNumber() + _indent + "LET " + varName + + // "(indexBase + " + el + ") = " + + // transform(elements.get(el))); + addCode(transformKeyword("LET ") + _targetVar + "(indexBase + " + el + ") = " + + transform(elements.get(el)), _indent, _disabled); + // END KGU#277 2016-10-13 + } + } + else { + addCode(transformKeyword("LET ") + _targetVar + " = " + + transform(_exprTokens.concatenate(null)), _indent, _disabled); + } + } + + // START KGU#779 2019-12-01: Issue #790 Type (record/enum) definitions hadn't been handled at all + /** + * Generates a type definition (as well as possible) from the given token list, depending on + * the export preferences (vintage BASIC / modern BASIC) + * @param _tokens - the lexically split type definition line + * @param _root - the owning Root + * @param _indent - the current indentation level + * @param _disabled - whether the element is disabled + */ + private boolean generateTypeDef(StringList _tokens, Root _root, String _indent, boolean _disabled) { + _tokens.removeAll(" "); + String typeName = _tokens.get(1); + String typeKey = ":" + typeName; + TypeMapEntry type = _root.getTypeInfo(routinePool).get(typeKey); + String indentPlus1 = _indent + this.getIndent(); + if (type == null) { + return false; + } + else if (this.wasDefHandled(_root, typeKey, false)) { + // Nothing to do + return true; + } + if (type.isRecord()) { + Map compSpecs = type.getComponentInfo(true); + if (this.optionCodeLineNumbering()) { + // We apply a QBASIC construct (see https://en.wikibooks.org/wiki/QBasic/Arrays_and_Types) + addCode(transformKeyword("TYPE ") + typeName, _indent, _disabled); + for (Entry entry: compSpecs.entrySet()) { + String compTypeName = "???"; + if (entry.getValue() != null) { + compTypeName = entry.getValue().getCanonicalType(true, true); + } + addCode(entry.getKey() + transformKeyword(" AS ") + transformType(compTypeName, "???"), indentPlus1, _disabled); + } + addCode(transformKeyword("END TYPE"), _indent, _disabled); + } + } + else if (type.isEnum()) { + StringList enumItems = type.getEnumerationInfo(); + if (this.optionCodeLineNumbering()) { + appendComment(_tokens.concatenate(null).replace("==", "="), _indent); + // In vintage BASIC, we will just generate separate variable definitions + int offset = 0; + String lastVal = ""; + for (int i = 0; i < enumItems.count(); i++) { + String[] itemSpec = enumItems.get(i).split("=", 2); + if (itemSpec.length > 1) { + lastVal = itemSpec[1].trim(); + offset = 0; + try { + int code = Integer.parseUnsignedInt(lastVal); + lastVal = ""; + offset = code; + } + catch (NumberFormatException ex) {} + } + addCode(transformKeyword("LET ") + itemSpec[0] + " = " + transform(lastVal) + (lastVal.isEmpty() ? "" : "+") + offset, _indent, _disabled); + offset++; + } + appendComment("end type "+ typeName, _indent); + } + else { + // We use a VisualBasic feature here (see https://docs.microsoft.com/de-de/dotnet/visual-basic/language-reference/statements/enum-statement) + addCode(transformKeyword("ENUM ") + typeName, _indent, _disabled); + for (int i = 0; i < enumItems.count(); i++) { + addCode(transform(enumItems.get(i)), indentPlus1, _disabled); + } + addCode(transformKeyword("END ENUM"), _indent, _disabled); + } + } + this.setDefHandled(_root.getSignatureString(false), typeKey); + return true; + } + + // START KGU#388 2019-12-01: Enh. #423 + /** + * Generates code that decomposes a record initializer into separate component assignments if + * necessary or converts it into the appropriate target language. + * @param _lValue - the left side of the assignment (without modifiers!) + * @param _recordValue - the record initializer according to Structorizer syntax + * @param _indent - current indentation level (as String) + * @param _isDisabled - indicates whether the code is o be commented out + * @param _typeEntry - used to interpret a simplified record initializer (may be null) + */ + // START KGU#559 2018-07-20: Enh. #563 + //protected void generateRecordInit(String _lValue, String _recordValue, String _indent, boolean _isDisabled) { + // HashMap comps = Instruction.splitRecordInitializer(_recordValue, null); + protected void generateRecordInit(String _lValue, String _recordValue, String _indent, boolean _isDisabled, TypeMapEntry _typeEntry) + { + // START KGU#771 2019-11-24: Bugfix #783 In case of an unknown record type we should at least write the original content + if (_typeEntry == null) { + addCode(transformKeyword("LET ") + transform(_lValue) + " = " + _recordValue + "\t" + this.commentSymbolLeft() + " FIXME: missing type information for struct! " + this.commentSymbolRight(), + _indent, false); + return; + } + HashMap comps = Instruction.splitRecordInitializer(_recordValue, _typeEntry, false); + for (Entry comp: comps.entrySet()) { + String compName = comp.getKey(); + String compVal = comp.getValue(); + if (!compName.startsWith("§") && compVal != null) { + // FIXME (KGU#560) 2018-07-21: how can we fix recursive initializers? See CGenerator + addCode(transformKeyword("LET ") + transform(_lValue) + "." + compName + " = " + transform(compVal), _indent, _isDisabled); + } + } + } + // END KGU#388 2019-12-01 + @Override protected void generateCode(Alternative _alt, String _indent) { @@ -556,20 +751,20 @@ protected void generateCode(Alternative _alt, String _indent) // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "IF " + condition + " THEN"); boolean disabled = _alt.isDisabled(); - addCode("IF " + condition + " THEN", _indent, disabled); + addCode(transformKeyword("IF ") + condition + " " + transformKeyword("THEN"), _indent, disabled); // END KGU#277 2016-10-13 generateCode(_alt.qTrue, indentPlusOne); if(_alt.qFalse.getSize() > 0) { // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "ELSE"); - addCode("ELSE", _indent, disabled); + addCode(transformKeyword("ELSE"), _indent, disabled); // END KGU#277 2016-10-13 generateCode(_alt.qFalse, indentPlusOne); } // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "END IF"); - addCode("END IF", _indent, disabled); + addCode(transformKeyword("END IF"), _indent, disabled); // END KGU#277 2016-10-13 } @@ -591,7 +786,7 @@ protected void generateCode(Case _case, String _indent) // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "SELECT CASE " + selection); boolean disabled =_case.isDisabled(); - addCode("SELECT CASE " + discriminator, _indent, disabled); + addCode(transformKeyword("SELECT CASE ") + discriminator, _indent, disabled); // END KGU#277 2016-10-13 for (int i=0; i<_case.qs.size()-1; i++) @@ -600,7 +795,7 @@ protected void generateCode(Case _case, String _indent) //code.add(this.getLineNumber() + indentPlusOne + "CASE " + _case.getText().get(i+1).trim()); // START KGU#453 2017-11-02: Issue #447 //addCode("CASE " + _case.getText().get(i+1).trim(), indentPlusOne, disabled); - addCode("CASE " + unbrokenText.get(i+1).trim(), indentPlusOne, disabled); + addCode(transformKeyword("CASE ") + unbrokenText.get(i+1).trim(), indentPlusOne, disabled); // END KGU#453 2017-11-02 // END KGU#277 2016-10-13 // code.add(_indent+_indent.substring(0,1)+_indent.substring(0,1)); @@ -615,13 +810,13 @@ protected void generateCode(Case _case, String _indent) { // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + indentPlusOne + "CASE ELSE"); - addCode("CASE ELSE", indentPlusOne, disabled); + addCode(transformKeyword("CASE ELSE"), indentPlusOne, disabled); // END KGU#277 2016-10-13 generateCode((Subqueue)_case.qs.get(_case.qs.size()-1), indentPlusTwo); } // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "END SELECT"); - addCode("END SELECT", _indent, disabled); + addCode(transformKeyword("END SELECT"), _indent, disabled); // END KGU#277 2016-10-13 } @@ -642,20 +837,20 @@ protected void generateCode(For _for, String _indent) String[] parts = _for.splitForClause(); String increment = ""; - if (!parts[3].trim().equals("1")) increment = " STEP " + parts[3]; + if (!parts[3].trim().equals("1")) increment = transformKeyword(" STEP ") + parts[3]; // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "FOR " + // parts[0] + " = " + transform(parts[1], false) + // " TO " + transform(parts[2], false) + increment); boolean disabled = _for.isDisabled(); - addCode("FOR " + parts[0] + " = " + transform(parts[1], false) + - " TO " + transform(parts[2], false) + increment, _indent, disabled); + addCode(transformKeyword("FOR ") + parts[0] + " = " + transform(parts[1], false) + + transformKeyword(" TO ") + transform(parts[2], false) + increment, _indent, disabled); // END KGU#277 2016-10-13 // END KGU 2015-11-02 generateCode(_for.q, _indent + this.getIndent()); // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "NEXT " + parts[0]); - addCode("NEXT " + parts[0], _indent, disabled); + addCode(transformKeyword("NEXT ") + parts[0], _indent, disabled); // END KGU#277 2016-10-13 // START KGU#78 2015-12-18: Enh. #23 @@ -757,7 +952,7 @@ protected boolean generateForInCode(For _for, String _indent) // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "DIM " + arrayName + "() AS " + itemType + " = {" + // items.concatenate(", ") + "}"); - addCode("DIM " + arrayName + "() AS " + itemType + " = {" + + addCode(transformKeyword("DIM ") + arrayName + "() " + transformKeyword("AS ") + itemType + " = {" + items.concatenate(", ") + "}", _indent, disabled); // END KGU#277 2016-10-13 valueList = arrayName; @@ -766,14 +961,14 @@ protected boolean generateForInCode(For _for, String _indent) // Creation of the loop header // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "FOR EACH " + var + " IN " + valueList); - addCode("FOR EACH " + var + " IN " + valueList, _indent, disabled); + addCode(transformKeyword("FOR EACH ") + var + transformKeyword(" IN ") + valueList, _indent, disabled); // END KGU#277 2016-10-13 // Creation of the loop body generateCode(_for.q, _indent + this.getIndent()); // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "NEXT " + var); - addCode("NEXT " + var, _indent, disabled); + addCode(transformKeyword("NEXT ") + var, _indent, disabled); // END KGU#277 2016-10-13 this.placeJumpTarget(_for, _indent); // Enh. #23: Takes care for correct jumps @@ -786,8 +981,10 @@ protected boolean generateForInCode(For _for, String _indent) @Override protected void generateCode(While _while, String _indent) { - - String condition = transform(_while.getText().getLongString(), false).trim(); + // START KGU#779 2019-12-01: Bugfix #790 (enh. #416) + //String condition = transform(_while.getText().getLongString(), false).trim(); + String condition = transform(_while.getUnbrokenText().getLongString(), false).trim(); + // END KGU#779 2019-12-01 // START KGU 2015-11-02 appendComment(_while, _indent); @@ -797,12 +994,12 @@ protected void generateCode(While _while, String _indent) // START KGU#2772 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "DO WHILE " + condition); boolean disabled = _while.isDisabled(); - addCode("DO WHILE " + condition, _indent, disabled); + addCode(transformKeyword("DO WHILE ") + condition, _indent, disabled); // END KGU#277 2016-10-13 generateCode(_while.q, _indent+this.getIndent()); // START KGU#2772 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "LOOP"); - addCode("LOOP", _indent, disabled); + addCode(transformKeyword("LOOP"), _indent, disabled); // END KGU#277 2016-10-13 // START KGU#78 2015-12-18: Enh. #23 @@ -813,8 +1010,10 @@ protected void generateCode(While _while, String _indent) @Override protected void generateCode(Repeat _repeat, String _indent) { - - String condition = transform(_repeat.getText().getLongString()).trim(); + // START KGU#779 2019-12-01: Bugfix #790 (enh. #416) + //String condition = transform(_repeat.getText().getLongString()).trim(); + String condition = transform(_repeat.getUnbrokenText().getLongString(), false).trim(); + // END KGU#779 2019-12-01 // START KGU 2015-11-02 appendComment(_repeat, _indent); @@ -823,12 +1022,12 @@ protected void generateCode(Repeat _repeat, String _indent) // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "DO"); boolean disabled = _repeat.isDisabled(); - addCode("DO", _indent, disabled); + addCode(transformKeyword("DO"), _indent, disabled); // END KGU#277 2016-10-13 generateCode(_repeat.q, _indent + this.getIndent()); // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "LOOP UNTIL " + condition); - addCode("LOOP UNTIL " + condition, _indent, disabled); + addCode(transformKeyword("LOOP UNTIL ") + condition, _indent, disabled); // END KGU#277 2016-10-13 // START KGU#78 2015-12-18: Enh. #23 @@ -846,12 +1045,12 @@ protected void generateCode(Forever _forever, String _indent) // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "DO"); boolean disabled = _forever.isDisabled(); - addCode("DO", _indent, disabled); + addCode(transformKeyword("DO"), _indent, disabled); // END KGU#277 2016-10-13 generateCode(_forever.q, _indent+this.getIndent()); // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "LOOP"); - addCode("LOOP", _indent, disabled); + addCode(transformKeyword("LOOP"), _indent, disabled); // END KGU#277 2016-10-13 // START KGU#78 2015-12-18: Enh. #23 @@ -867,13 +1066,15 @@ protected void generateCode(Call _call, String _indent) appendComment(_call, _indent); // END KGU 2014-11-16 Root owningRoot = Element.getRoot(_call); - for (int i=0; i<_call.getUnbrokenText().count(); i++) + StringList lines = _call.getUnbrokenText(); + for (int i=0; i < lines.count(); i++) { // START KGU#2 2015-12-18: Enh. #9 This may require a CALL command prefix //code.add(_indent+transform(_call.getText().get(i))); // START KGU#371 2019-03-08: Enh. #385 Support for declared optional arguments //String line = transform(_call.getText().get(i)); - String line = _call.getUnbrokenText().get(i); + String line = lines.get(i); + boolean isAsgnmt = Instruction.isAssignment(line); if (i == 0 && this.getOverloadingLevel() == OverloadingLevel.OL_NO_OVERLOADING && (routinePool != null) && line.endsWith(")")) { Function call = _call.getCalledRoutine(); @@ -891,9 +1092,12 @@ protected void generateCode(Call _call, String _indent) } } // END KGU#371 2019-03-08 - if (!line.startsWith("LET") || line.indexOf(" = ") < 0) + // START KGU#778 2019-12-01: Bugfix #789 - The detection of function calls was corrupted by patch #385 + //if (!line.startsWith("LET") || line.indexOf(" = ") < 0) + if (!isAsgnmt) + // END KGU#778 2019-12-01 { - line = "CALL " + line; + line = transformKeyword("CALL ") + line; } // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + line); @@ -922,7 +1126,10 @@ protected void generateCode(Jump _jump, String _indent) //} boolean isEmpty = true; - StringList lines = _jump.getText(); + // START KGU#779 2019-12-01: Bugfix #790 (enh. #416) + //StringList lines = _jump.getText(); + StringList lines = _jump.getUnbrokenText(); + // END KGU#779 2019-12-01 String preReturn = CodeParser.getKeywordOrDefault("preReturn", "return"); String preThrow = CodeParser.getKeywordOrDefault("preThrow", "throw"); for (int i = 0; isEmpty && i < lines.count(); i++) { @@ -941,7 +1148,7 @@ protected void generateCode(Jump _jump, String _indent) //code.add(_indent + this.getLineNumber() + this.procName + " = " + argument + " : END"); // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "RETURN " + argument); - addCode( "RETURN " + argument, _indent, disabled); + addCode(transformKeyword("RETURN ") + argument, _indent, disabled); // END KGU#277 2016-10-13 } } @@ -949,7 +1156,7 @@ else if (Jump.isExit(line)) { // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "STOP"); - addCode("STOP", _indent, disabled); + addCode(transformKeyword("STOP"), _indent, disabled); // END KGU#277 2016-10-13 } // START KGU#686 2019-03-18: Enh. #56 @@ -976,7 +1183,7 @@ else if (this.jumpTable.containsKey(_jump)) } // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "GOTO " + label); - addCode("GOTO " + label, _indent, disabled); + addCode(transformKeyword("GOTO ") + label, _indent, disabled); // END KGU#277 2016-10-13 isEmpty = false; // Leave the above loop now } @@ -998,7 +1205,7 @@ else if (!isEmpty) } // START KGU#277 2016-10-13: Enh. #270 //code.add(this.getLineNumber() + _indent + "GOTO " + label); - addCode("GOTO " + label, _indent, disabled); + addCode(transformKeyword("GOTO ") + label, _indent, disabled); // END KGU#277 2016-10-13 isEmpty = false; // Leave the above loop now } @@ -1160,7 +1367,7 @@ protected String generateHeader(Root _root, String _indent, String _procName, String signature = _root.getMethodName(); if (_root.isSubroutine()) { boolean isFunction = _resultType != null || this.returns || this.isResultSet || this.isFunctionNameSet; - pr = isFunction ? "FUNCTION" : "SUB"; + pr = transformKeyword(isFunction ? "FUNCTION" : "SUB"); // Compose the function header signature += "("; @@ -1196,12 +1403,12 @@ protected String generateHeader(Root _root, String _indent, String _procName, signature += ")"; if (_resultType != null) { - signature += " AS " + transformType(_resultType, "Real"); + signature += transformKeyword(" AS ") + transformType(_resultType, "Real"); } furtherIndent += this.getIndent(); - } - code.add(this.getLineNumber() + _indent + pr + " " + signature); - + } + code.add(this.getLineNumber() + _indent + pr + " " + signature); + return furtherIndent; } @@ -1214,10 +1421,29 @@ protected String generatePreamble(Root _root, String _indent, StringList _varNam // Old BASIC dialocts with line numbers usually don't support declarations if (!this.optionCodeLineNumbering()) { - String indentPlusOne = _indent + this.getIndent(); - appendComment("TODO: declare your variables here:", _indent ); + appendComment("TODO: Check and accomplish your variable declarations here:", _indent ); for (int v = 0; v < _varNames.count(); v++) { - appendComment("DIM " + _varNames.get(v) + " AS ", indentPlusOne); + // START KGU#542 2019-12-01: Enh. #739 Don't do this for enumeration constants here + //appendComment(transformKeyword("DIM ") + _varNames.get(v) + transformKeyword(" AS") + " ", indentPlusOne); + String varName = _varNames.get(v); + String constVal = null; + if (((constVal = _root.constants.get(varName)) == null || !constVal.startsWith(":")) + && !this.wasDefHandled(_root, varName, true)) { + TypeMapEntry type = _root.getTypeInfo().get(varName); + String typeName = "???"; + if (type != null) { + StringList typeNames = this.getTransformedTypes(type, true); + if (typeNames.count() == 1) { + typeName = typeNames.get(0); + } + while (typeName.startsWith("@")) { + varName += "()"; + typeName = typeName.substring(1); + } + } + addCode(transformKeyword("DIM ") + varName + transformKeyword(" AS ") + typeName, _indent, false); + } + // END KGU#542 2019-12-01 } appendComment("", _indent); } @@ -1246,7 +1472,7 @@ else if (isResultSet) int vx = varNames.indexOf("result", false); result = varNames.get(vx); } - code.add(this.getLineNumber() + _indent + "RETURN " + result); + code.add(this.getLineNumber() + _indent + transformKeyword("RETURN ") + result); } return _indent; } @@ -1269,7 +1495,7 @@ protected void generateFooter(Root _root, String _indent) endPhrase += " SUB"; } } - code.add(_indent + this.getLineNumber() + endPhrase); + code.add(_indent + this.getLineNumber() + transformKeyword(endPhrase)); if (this.optionCodeLineNumbering()) { diff --git a/src/lu/fisch/structorizer/generators/CGenerator.java b/src/lu/fisch/structorizer/generators/CGenerator.java index 244c495e..a881c7d6 100644 --- a/src/lu/fisch/structorizer/generators/CGenerator.java +++ b/src/lu/fisch/structorizer/generators/CGenerator.java @@ -94,6 +94,10 @@ * Kay Gürtzig 2019-10-03 Bugfix #756: Transformation damage on expressions containing "<-" and brackets * Kay Gürtzig 2019-11-08 Bugfix #769: Undercomplex selector list splitting in CASE generation mended * Kay Gürtzig 2019-11-12 Bugfix #752: Outcommenting of incomplete declarations ended + * Kay Gürtzig 2019-11-17 Enh. #739: Modifications for support of enum type definitions (TODO) + * Kay Gürtzig 2019-11-24 Bugfix #783: Defective record initializers were simpy skipped without trace + * Kay Gürtzig 2019-11-30 Bugfix #782: Handling of global/local declarations mended + * Kay Gürtzig 2019-12-02 KGU#784 Type descriptor transformation improved. * ****************************************************************************************************** * @@ -320,6 +324,14 @@ protected boolean wantsSizeInArrayType() return true; } // END KGU#560 2018-07-22 + + // START KGU#784 2019-12-02 + /** @return whether the index range for array declarations is to be appended to the element type (otherwise to the variable name) */ + protected boolean arrayBracketsAtTypeName() + { + return false; + } + // END KGU#784 2019-12-02 // START KGU#18/KGU#23 2015-11-01 Transformation decomposed /* (non-Javadoc) @@ -567,9 +579,19 @@ protected String transformType(String _type, String _default) { protected String transformTypeWithLookup(String _type, String _default) { TypeMapEntry typeInfo = this.typeMap.get(":" + _type); // The typeInfo might be an alias, in this case no specific measures are necessary - if (typeInfo != null && typeInfo.isRecord() && _type.equals(typeInfo.typeName)) { - _type = this.transformRecordTypeRef(typeInfo.typeName, false); + // START KGU#542 2019-11-17: Enh. #739 + //if (typeInfo != null && typeInfo.isRecord() && _type.equals(typeInfo.typeName)) { + // _type = this.transformRecordTypeRef(typeInfo.typeName, false); + //} + if (typeInfo != null && (typeInfo.isRecord() || typeInfo.isEnum()) && _type.equals(typeInfo.typeName)) { + if (typeInfo.isRecord()) { + _type = this.transformRecordTypeRef(typeInfo.typeName, false); + } + else { + _type = this.transformEnumTypeRef(typeInfo.typeName); + } } + // END KGU#542 2019-11-17 else { _type = transformType(_type, _default); } @@ -585,7 +607,7 @@ protected String transformArrayDeclaration(String _typeDescr, String _varName) String decl = ""; if (_typeDescr.toLowerCase().startsWith("array") || _typeDescr.endsWith("]")) { // TypeMapEntries are really good at analysing array definitions - TypeMapEntry typeInfo = new TypeMapEntry(_typeDescr, null, null, null, 0, false, true, false); + TypeMapEntry typeInfo = new TypeMapEntry(_typeDescr, null, null, null, 0, false, true); String canonType = typeInfo.getTypes().get(0); decl = this.makeArrayDeclaration(canonType, _varName, typeInfo).trim(); } @@ -610,7 +632,7 @@ protected String transformArrayDeclaration(String _typeDescr, String _varName) protected String transformRecordInit(String constValue, TypeMapEntry typeInfo) { // START KGU#559 2018-07-20: Enh. #563 - smarter initializer evaluation //HashMap comps = Instruction.splitRecordInitializer(constValue); - HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo); + HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo, false); // END KGU#559 2018-07-20 LinkedHashMap compInfo = typeInfo.getComponentInfo(true); StringBuilder recordInit = new StringBuilder("{"); @@ -693,6 +715,7 @@ protected boolean isInternalDeclarationAllowed() * The returned type description will have to be split before the first * occurring opening bracket in order to place the variable or type name there. * @param typeInfo - the defining or derived TypeMapInfo of the type + * @param definingWithin - a possible outer type context * @return a String suited as C type description in declarations etc. */ @Override @@ -706,8 +729,13 @@ protected String transformTypeFromEntry(TypeMapEntry typeInfo, TypeMapEntry defi if (typeInfo.isRecord()) { elType = transformRecordTypeRef(elType, typeInfo == definingWithin); } + // START KGU#542 2019-11-17: Enh. #739 - support for enum types + else if (typeInfo.isEnum()) { + elType = transformEnumTypeRef(elType); + } + // END KGU#542 2019-11-17 else { - elType = transformType(elType, "/*???*/"); + elType = transformType(elType, "???"); } _typeDescr = elType; for (int i = 0; i < nLevels; i++) { @@ -740,6 +768,19 @@ protected String transformTypeFromEntry(TypeMapEntry typeInfo, TypeMapEntry defi protected String transformRecordTypeRef(String structName, boolean isRecursive) { return "struct " + structName + (isRecursive ? " * " : ""); } + + // START KGU#542 2019-11-17: Enh. #739 + /** + * Special adaptation of enum type name references in C-like languages, e.g. C + * adds a prefix "enum" wherever it is used. C++ doesn't need to, Java and C# + * don't, so the inheriting classes must override this. + * @param enumName - name of the structured type + * @return the prepared reference string + */ + protected String transformEnumTypeRef(String enumName) { + return "enum " + enumName; + } + // END KGU#542 2019-11-17 /** * Adds the type definitions for all types in {@code _root.getTypeInfo()}. @@ -771,9 +812,9 @@ protected void generateTypeDef(Root _root, String _typeName, TypeMapEntry _type, if (this.wasDefHandled(_root, typeKey, true)) { return; } + String indentPlus1 = _indent + this.getIndent(); appendDeclComment(_root, _indent, typeKey); if (_type.isRecord()) { - String indentPlus1 = _indent + this.getIndent(); addCode("struct " + _type.typeName + " {", _indent, _asComment); for (Entry compEntry: _type.getComponentInfo(false).entrySet()) { addCode(transformTypeFromEntry(compEntry.getValue(), _type) + "\t" + compEntry.getKey() + ";", @@ -781,6 +822,23 @@ protected void generateTypeDef(Root _root, String _typeName, TypeMapEntry _type, } addCode("};", _indent, _asComment); } + // START KGU#542 2019-11-17: Enh. #739 + else if (_type.isEnum()) { + StringList items = _type.getEnumerationInfo(); + String itemList = items.concatenate(", "); + if (itemList.length() > 70) { + addCode("enum " + _type.typeName + "{", _indent, _asComment); + for (int i = 0; i < items.count(); i++) { + // FIXME: We might have to transform the value... + addCode(items.get(i) + (i < items.count() -1 ? "," : ""), indentPlus1, _asComment); + } + addCode("};", _indent, _asComment); + } + else { + addCode("enum " + _type.typeName + "{" + itemList + "};", _indent, _asComment); + } + } + // END KGU#542 2019-11-17 else { addCode("typedef " + this.transformTypeFromEntry(_type, null) + " " + _typeName + ";", _indent, _asComment); @@ -870,7 +928,7 @@ protected boolean generateInstructionLine(Instruction _inst, String _indent, boo pureExprTokens = pureTokens.subSequence(pureTokens.indexOf("<-")+1, pureTokens.count()); } String codeLine = null; - String varName = Instruction.getAssignedVarname(pureTokens); + String varName = Instruction.getAssignedVarname(pureTokens, false); boolean isDecl = Instruction.isDeclaration(line); //exprTokens.removeAll(" "); if (!this.suppressTransformation && (isDecl || exprTokens != null)) { @@ -886,6 +944,7 @@ protected boolean generateInstructionLine(Instruction _inst, String _indent, boo // we must cut off the type specification (i.e. all text preceding the // variable name). Root root = Element.getRoot(_inst); + StringList paramNames = root.getParameterNames(); // START KGU#375 2017-04-12: Enh. #388 special treatment of constants if (pureTokens.get(0).equals("const")) { // Cases 1.1.1 or 2.1 @@ -895,7 +954,7 @@ protected boolean generateInstructionLine(Instruction _inst, String _indent, boo // We try to enrich or accomplish defective type information if (root.constants.get(varName) != null) { this.appendDeclaration(root, varName, _indent, true); - // START KGU#424 2017-09-26: Avoid the comment here if the element contains mere declarations + // KGU#424: Avoid the comment here if the element contains mere declarations return true; } } @@ -988,6 +1047,33 @@ else if (!isDecl && exprTokens != null) { // Case 1.2 // Combine variable access as is codeLine = transform(tokens.subSequence(0, posAsgn).concatenate()).trim(); + // START KGU#767 2019-11-30: Bugfix #782 maybe we must introduce a postponed declaration here + if (varName != null + && Function.testIdentifier(varName, null) + && codeLine.indexOf(varName) + varName.length() == codeLine.length() + && !paramNames.contains(varName) + && !this.wasDefHandled(root, varName, false)) { + TypeMapEntry type = this.typeMap.get(varName); + String typeName = "???"; + if (type != null) { + typeName = transformTypeFromEntry(type, null); + if (type.isRecord()) { + isDecl = true; + } + // START KGU#784 2019-12-02 + else if (type.isArray() && !this.arrayBracketsAtTypeName()) { + int posBrack = typeName.indexOf("["); + if (posBrack > 0) { + codeLine += typeName.substring(posBrack); + typeName = typeName.substring(0, posBrack); + } + } + // END KGU#784 2019-12-02 + } + codeLine = typeName + " " + codeLine; + this.setDefHandled(root.getSignatureString(false), varName); + } + // END KGU#767 2019-11-30 } // Now we care for a possible assignment if (codeLine != null && exprTokens != null && pureExprTokens.count() > 0) { @@ -1009,11 +1095,11 @@ else if (!isDecl && exprTokens != null) { appendComment(_inst, _indent); commentInserted = true; } - // END KGU#424 2017-09-26 // FIXME: Possibly codeLine (the lval string) might be too much as first argument // START KGU#559 2018-07-20: Enh. #563 //this.generateRecordInit(codeLine, pureExprTokens.concatenate(), _indent, isDisabled, null); this.generateRecordInit(codeLine, pureExprTokens.concatenate(), _indent, isDisabled, recType); + // END KGU#559 2018-07-20 return commentInserted; } } @@ -1026,6 +1112,27 @@ else if (!isDecl && exprTokens != null) { if (elemType != null && elemType.startsWith("@")) { elemType = elemType.substring(1); } + // START KGU #784 2019-12-02: varName is only part of the left side, there may be indices, so reduce the type if so + int posIdx = codeLine.indexOf(varName) + varName.length(); + String indices = codeLine.substring(posIdx).trim(); + while (elemType.startsWith("@") && indices.startsWith("[")) { + elemType = elemType.substring(1); + StringList indexList = Element.splitExpressionList(indices.substring(1), ",", true); + indexList.remove(0); // Drop first index expression (has already been handled) + // Are there perhaps more indices within the same bracket pair (comma-separated list)? + while (indexList.count() > 1 && elemType.startsWith("@")) { + indexList.remove(0); + elemType = elemType.substring(1); + } + if (indexList.isEmpty()) { + indices = ""; + } + else if (indexList.get(0).trim().startsWith("]")) { + // This should be the tail + indices = indexList.get(0).substring(1); + } + } + // END KGU #784 2019-12-02 } expr = this.transformOrGenerateArrayInit(codeLine, items.subSequence(0, items.count()-1), _indent, isDisabled, elemType, isDecl); if (expr == null) { @@ -1322,6 +1429,7 @@ protected boolean generateForInCode(For _for, String _indent) // do if items are heterogeneous? We will make use of the typeMap and // hope to get sensible information. Otherwise we add a TODO comment. int nItems = items.count(); + boolean allChar = true; // KGU#782 2019-12-02: We now also detect char elements boolean allInt = true; boolean allDouble = true; boolean allString = true; @@ -1331,7 +1439,10 @@ protected boolean generateForInCode(For _for, String _indent) String item = items.get(i); String type = Element.identifyExprType(this.typeMap, item, false); itemTypes.add(this.transformType(type, "int")); - if (!type.equals("int") && !type.equals("boolean")) { + if (!type.equals("char")) { + allChar = false; + } + if (!type.equals("int") && !type.equals("boolean") && !type.equals("char")) { allInt = false; } // START KGU#355 2017-03-30: #365 - allow type conversion @@ -1340,11 +1451,12 @@ protected boolean generateForInCode(For _for, String _indent) // END KGU#355 2017-03-30 allDouble = false; } - if (!type.equals("String")) { + if (!type.equals("String") && !type.equals("char")) { allString = false; } } - if (allInt) itemType = "int"; + if (allChar) itemType = "char"; + else if (allInt) itemType = "int"; else if (allDouble) itemType = "double"; else if (allString) itemType = "char*"; String arrayLiteral = "{" + items.concatenate(", ") + "}"; @@ -1454,6 +1566,7 @@ else if (typeInfo != null && typeInfo.getCanonicalType(true, true).equalsIgnoreC if (itemType.startsWith("union ")) { this.appendComment("TODO: Extract the value from the appropriate component here and care for type conversion!", _indent); } + // Well, this is local to the loop, so it won't cause trouble with an automatic declaration in the outer context addCode(this.getIndent() + (itemType + " " + itemVar + " = " + arrayName + "[" + indexName + "];").trim(), indent, isDisabled); @@ -1942,7 +2055,7 @@ protected String generateHeader(Root _root, String _indent, String _procName, // START KGU#140 2017-01-31: Enh. #113: Proper conversion of array types //fnHeader += (transformType(_paramTypes.get(p), "/*type?*/") + " " + // _paramNames.get(p)).trim(); - fnHeader += transformArrayDeclaration(transformTypeWithLookup(_paramTypes.get(p), "/*type?*/").trim(), _paramNames.get(p)); + fnHeader += transformArrayDeclaration(transformTypeWithLookup(_paramTypes.get(p), "???").trim(), _paramNames.get(p)); // END KGU#140 2017-01-31 } fnHeader += ")"; @@ -2064,6 +2177,11 @@ protected void appendDeclaration(Root _root, String _name, String _indent, boole TypeMapEntry typeInfo = typeMap.get(_name); StringList types = null; String constValue = _root.constants.get(_name); + // START KGU#542 2019-11-17: Enh. #739 Don't add enumerator constant definitions + if (constValue != null && constValue.startsWith(":")) { + return; // If the value string starts with a colon then it originates in an enumeration type. + } + // END KGU#542 2019-11-17 String transfConst = transformType("const", ""); if (typeInfo != null) { // START KGU#388 2017-09-30: Enh. #423 @@ -2071,6 +2189,11 @@ protected void appendDeclaration(Root _root, String _name, String _indent, boole if (typeInfo.isRecord()) { types = StringList.getNew(this.transformRecordTypeRef(typeInfo.typeName, false)); } + // START KGU#542 2019-11-17: Enh. #739 - support for enum types + else if (typeInfo.isEnum()) { + types = StringList.getNew(this.transformEnumTypeRef(typeInfo.typeName)); + } + // END KGU#542 2019-11-17 else { types = getTransformedTypes(typeInfo, true); } @@ -2089,7 +2212,7 @@ protected void appendDeclaration(Root _root, String _name, String _indent, boole if (!type.isEmpty()) { types = StringList.getNew(transformType(type, "int")); // We place a faked workaround entry - typeMap.put(_name, new TypeMapEntry(type, null, null, _root, 0, true, false, true)); + typeMap.put(_name, new TypeMapEntry(type, null, null, _root, 0, true, false)); } // START KGU#730 2019-09-25: Bugfix #752 - we must provide something lest the definition should go lost else if (_fullDecl) { @@ -2166,9 +2289,15 @@ else if (_fullDecl) { } // Add a comment if there is no type info or internal declaration is not allowed else if (types == null || _fullDecl){ + String typeName = "???"; + // START KGU#771 2019-11-24: Bugfix #783 + if (types != null) { + typeName = types.get(0) + "???"; + } + // END KGU#771 2019-11-24 // START #730 2019-11-12: Issue #752 don't comment it out, a missing declaration is a syntax error anyway //appendComment(_name + ";", _indent); - addCode("??? " + _name + ";", _indent, false); + addCode(typeName + " " + _name + ";", _indent, false); // END KGU#730 2019-11-12 // START KGU#424 2017-09-26: Ensure the declaration comment doesn't get lost setDefHandled(_root.getSignatureString(false), _name); @@ -2220,7 +2349,14 @@ protected String getModifiers(Root _root, String _name) { // HashMap comps = Instruction.splitRecordInitializer(_recordValue, null); protected void generateRecordInit(String _lValue, String _recordValue, String _indent, boolean _isDisabled, TypeMapEntry _typeEntry) { - HashMap comps = Instruction.splitRecordInitializer(_recordValue, _typeEntry); + // START KGU#771 2019-11-24: Bugfix #783 In case of an unknown record type we should at least write the original content + if (_typeEntry == null) { + addCode(_lValue + " = " + _recordValue + ";\t" + this.commentSymbolLeft() + " FIXME: missing type information for struct! " + this.commentSymbolRight(), + _indent, false); + return; + } + // END KGU#771 2019-11-24 + HashMap comps = Instruction.splitRecordInitializer(_recordValue, _typeEntry, false); // END KGU#559 2018-07-20 for (Entry comp: comps.entrySet()) { String compName = comp.getKey(); @@ -2252,7 +2388,7 @@ protected void generateAssignment(String _lValue, String _expr, String _indent, if (pureExprTokens.count() >= 3 && posBrace <= 1) { if (posBrace == 1 && Function.testIdentifier(pureExprTokens.get(0), null)) { // Record initializer - String typeName = pureExprTokens.get(0); + String typeName = pureExprTokens.get(0); TypeMapEntry recType = this.typeMap.get(":"+typeName); this.generateRecordInit(_lValue, _expr, _indent, _isDisabled, recType); } diff --git a/src/lu/fisch/structorizer/generators/COBOLGenerator.java b/src/lu/fisch/structorizer/generators/COBOLGenerator.java index 037b48ea..f12ea19f 100644 --- a/src/lu/fisch/structorizer/generators/COBOLGenerator.java +++ b/src/lu/fisch/structorizer/generators/COBOLGenerator.java @@ -413,7 +413,7 @@ protected void appendDeclaration(Root _root, String _name, String _indent) String cobName = this.transformName(_name); TypeMapEntry typeInfo = typeMap.get(_name); StringList types = null; - String constValue = _root.constants.get(_name); + String constValue = _root.getConstValueString(_name); String transfConst = transformType("const", ""); if (typeInfo != null) { types = getTransformedTypes(typeInfo, false); @@ -424,7 +424,7 @@ else if (constValue != null) { if (!type.isEmpty()) { types = StringList.getNew(transformType(type, "int")); // We place a faked workaround entry - typeMap.put(_name, new TypeMapEntry(type, null, null, _root, 0, true, false, true)); + typeMap.put(_name, new TypeMapEntry(type, null, null, _root, 0, true, false)); } } // If the type is unambiguous and has no C-style declaration or may not be diff --git a/src/lu/fisch/structorizer/generators/CPlusPlusGenerator.java b/src/lu/fisch/structorizer/generators/CPlusPlusGenerator.java index 0e82aea3..34ad0c11 100644 --- a/src/lu/fisch/structorizer/generators/CPlusPlusGenerator.java +++ b/src/lu/fisch/structorizer/generators/CPlusPlusGenerator.java @@ -58,6 +58,8 @@ * Kay Gürtzig 2019-02-14 Enh. #680: Support for input instructions with several variables * Kay Gürtzig 2019-03-08 Enh. #385: Support for parameter default values * Kay Gürtzig 2019-03-30 Issue #696: Type retrieval had to consider an alternative pool + * Kay Gürtzig 2019-10-18 Enh. #739: Support for enum types + * Kay Gürtzig 2019-12-02 KGU#784 Defective type descriptions in argument lists and thread function operators * ****************************************************************************************************** * @@ -72,7 +74,6 @@ import java.util.HashMap; import java.util.LinkedList; -import java.util.Map.Entry; import lu.fisch.structorizer.elements.Element; import lu.fisch.structorizer.elements.For; @@ -288,37 +289,39 @@ protected String composeInputItems(StringList _inputVarItems) } // END KGU#653 2019-02-14 - // START KGU#388 2017-09-27: Enh.#423 - /** - * Adds a typedef for the type passed in by {@code _typeEnry} if it hadn't been defined - * globally or in the preamble before. - * @param _root - the originating Root - * @param _type - the type map entry the definition for which is requested here - * @param _indent - the current indentation - * @param _asComment - if the type deinition is only to be added as comment (disabled) - */ - @Override - protected void generateTypeDef(Root _root, String _typeName, TypeMapEntry _type, String _indent, boolean _asComment) { - String typeKey = ":" + _typeName; - if (this.wasDefHandled(_root, typeKey, true)) { - return; - } - appendDeclComment(_root, _indent, typeKey); - if (_type.isRecord()) { - String indentPlus1 = _indent + this.getIndent(); - addCode("struct " + _typeName + " {", _indent, _asComment); - for (Entry compEntry: _type.getComponentInfo(false).entrySet()) { - addCode(transformTypeFromEntry(compEntry.getValue(), _type) + "\t" + compEntry.getKey() + ";", - indentPlus1, _asComment); - } - addCode("};", _indent, _asComment); - } - else { - addCode("typedef " + this.transformTypeFromEntry(_type, null) + " " + _typeName + ";", - _indent, _asComment); - } - } - // END KGU#388 2017-09-27 +// START KGU#542 2019-11-17: Enh. #739: This code was identical to that of super +// // START KGU#388 2017-09-27: Enh.#423 +// /** +// * Adds a typedef for the type passed in by {@code _typeEnry} if it hadn't been defined +// * globally or in the preamble before. +// * @param _root - the originating Root +// * @param _type - the type map entry the definition for which is requested here +// * @param _indent - the current indentation +// * @param _asComment - if the type deinition is only to be added as comment (disabled) +// */ +// @Override +// protected void generateTypeDef(Root _root, String _typeName, TypeMapEntry _type, String _indent, boolean _asComment) { +// String typeKey = ":" + _typeName; +// if (this.wasDefHandled(_root, typeKey, true)) { +// return; +// } +// appendDeclComment(_root, _indent, typeKey); +// if (_type.isRecord()) { +// String indentPlus1 = _indent + this.getIndent(); +// addCode("struct " + _typeName + " {", _indent, _asComment); +// for (Entry compEntry: _type.getComponentInfo(false).entrySet()) { +// addCode(transformTypeFromEntry(compEntry.getValue(), _type) + "\t" + compEntry.getKey() + ";", +// indentPlus1, _asComment); +// } +// addCode("};", _indent, _asComment); +// } +// else { +// addCode("typedef " + this.transformTypeFromEntry(_type, null) + " " + _typeName + ";", +// _indent, _asComment); +// } +// } +// // END KGU#388 2017-09-27 +// END KGU#542 2019-11-17 // START KGU#61 2016-03-22: Enh. #84 - Support for FOR-IN loops /** @@ -485,13 +488,21 @@ private String makeArgList(StringList varNames, HashMap ty for (int v = 0; v < varNames.count(); v++) { String varName = varNames.get(v); TypeMapEntry typeEntry = typeMap.get(varName); - String typeSpec = "/*type?*/"; + String typeSpec = "???"; boolean isArray = false; if (typeEntry != null) { isArray = typeEntry.isArray(); StringList typeSpecs = this.getTransformedTypes(typeEntry, false); if (typeSpecs.count() == 1) { - typeSpec = typeSpecs.get(0); + // START KGU#784 2019-12-02 + //typeSpec = typeSpecs.get(0); + typeSpec = this.transformTypeFromEntry(typeEntry, null); + int posBrack = typeSpec.indexOf("["); + if (posBrack > 0) { + varName += typeSpec.substring(posBrack); + typeSpec = typeSpec.substring(0, posBrack); + } + // END KGU#784 2019-12-02 } } argList += (v > 0 ? ", " : "") + typeSpec + (isArray ? " " : "& ") + varName; @@ -628,7 +639,7 @@ protected String generateHeader(Root _root, String _indent, String _procName, // START KGU#140 2017-01-31: Enh. #113: Proper conversion of array types //fnHeader += (transformType(_paramTypes.get(p), "/*type?*/") + " " + // _paramNames.get(p)).trim(); - fnHeader += transformArrayDeclaration(transformType(_paramTypes.get(p), "/*type?*/").trim(), _paramNames.get(p)); + fnHeader += transformArrayDeclaration(transformType(_paramTypes.get(p), "???").trim(), _paramNames.get(p)); // START KGU#371 2019-03-07: Enh. #385 String defVal = defaultVals.get(p); if (defVal != null) { @@ -676,6 +687,16 @@ protected String transformRecordTypeRef(String structName, boolean isRecursive) return structName + (isRecursive ? " * " : ""); } + // START KGU#542 2019-11-17: Enh. #739 + /* (non-Javadoc) + * @see lu.fisch.structorizer.generators.CGenerator#transformEnumTypeRef(java.lang.String) + */ + @Override + protected String transformEnumTypeRef(String enumName) { + return enumName; + } + // END KGU#542 2019-11-17 + @Override protected void generateIOComment(Root _root, String _indent) { diff --git a/src/lu/fisch/structorizer/generators/CSharpGenerator.java b/src/lu/fisch/structorizer/generators/CSharpGenerator.java index ae9e852f..5c729fd3 100644 --- a/src/lu/fisch/structorizer/generators/CSharpGenerator.java +++ b/src/lu/fisch/structorizer/generators/CSharpGenerator.java @@ -228,6 +228,12 @@ protected boolean wantsSizeInArrayType() } // END KGU#560 2018-07-22 + @Override + protected boolean arrayBracketsAtTypeName() + { + return true; + } + // START KGU#18/KGU#23 2015-11-01 Transformation decomposed /* (non-Javadoc) * @see lu.fisch.structorizer.generators.CGenerator#getInputReplacer(boolean) @@ -381,6 +387,18 @@ protected boolean isInternalDeclarationAllowed() } // END KGU#332 2017-04-14 + // START KGU#784 2019-12-02 + @Override + protected String transformType(String _type, String _default) + { + if (_type != null && (_type.equals("String") || _type.equals("Object"))) { + _type = _type.toLowerCase(); + } + return super.transformType(_type, _default); + } + // END KGU#784 2019-12-02 + + // START KGU#388 2017-09-28: Enh. #423 /* (non-Javadoc) * @see lu.fisch.structorizer.generators.CGenerator#transformRecordInit(java.lang.String, lu.fisch.structorizer.elements.TypeMapEntry) @@ -390,13 +408,14 @@ protected String transformRecordInit(String constValue, TypeMapEntry typeInfo) { // This is practically identical to Java // START KGU#559 2018-07-20: Enh. #563 - smarter record initialization //HashMap comps = Instruction.splitRecordInitializer(constValue); - HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo); + HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo, false); // END KGU#559 2018-07-20 LinkedHashMap compInfo = typeInfo.getComponentInfo(true); String recordInit = "new " + typeInfo.typeName + "("; boolean isFirst = true; for (Entry compEntry: compInfo.entrySet()) { String compName = compEntry.getKey(); + TypeMapEntry compType = compEntry.getValue(); String compVal = comps.get(compName); if (isFirst) { isFirst = false; @@ -408,12 +427,12 @@ protected String transformRecordInit(String constValue, TypeMapEntry typeInfo) { if (compVal == null) { recordInit += "null"; } - else if (compEntry.getValue().isRecord()) { - recordInit += transformRecordInit(compVal, compEntry.getValue()); + else if (compType != null && compType.isRecord()) { + recordInit += transformRecordInit(compVal, compType); } // START KGU#561 2018-07-21: Bugfix #564 - else if (compEntry.getValue().isArray() && compVal.startsWith("{") && compVal.endsWith("}")) { - String elemType = compEntry.getValue().getCanonicalType(true, false).substring(1); + else if (compType != null && compType.isArray() && compVal.startsWith("{") && compVal.endsWith("}")) { + String elemType = compType.getCanonicalType(true, false).substring(1); recordInit += "new " + this.transformType(elemType, "object") + "[]" + compVal; } // END KGU#561 2018-07-21 @@ -655,11 +674,11 @@ protected boolean generateForInCode(For _for, String _indent) if (listType != null && listType.isArray() && (itemType = listType.getCanonicalType(true, false)) != null && itemType.startsWith("@")) { - itemType = this.transformType(itemType.substring(1), "Object"); + itemType = this.transformType(itemType.substring(1), "object"); } else { itemType = "Object"; - this.appendComment("TODO: Select a more sensible item type than Object", indent); + this.appendComment("TODO: Select a more sensible item type than object", indent); this.appendComment(" and/or prepare the elements of the array.", indent); } // END KGU#388 2017-09-28 @@ -850,11 +869,14 @@ private StringList makeArgList(StringList varNames, HashMap + * 1. by diagram {@code _root} itself or + * 2. by one of the diagrams included by {@code _root} if {@code _involveIncludables} is true. + * If not and {@code _setDefindIfNot} is true then registers the {@code _id} with {@code _root} + * in {@link #declaredStuff}. + * @param _root - the currently exported {@link Root} + * @param _id - the name of a constant, variable, or type (in the latter case prefixed with ':') + * @param _setDefinedIfNot - whether the name is to be registered for {@code _root} now if not + * @param _involveIncludables - whether the included diagrams are also to be consulted + * @return true if there had already been a definition before + * @see #setDefHandled(String, String) + */ + protected boolean wasDefHandled(Root _root, String _id, boolean _setDefinedIfNot, boolean _involveIncludables) + // END KGU#767 2019-11-24 { String signature = _root.getSignatureString(false); StringList definedIds = this.declaredStuff.get(signature); boolean handled = definedIds != null && definedIds.contains(_id); - if (_root.includeList != null) { + if (_involveIncludables && _root.includeList != null) { for (int i = 0; !handled && i < _root.includeList.count(); i++) { String inclName = _root.includeList.get(i); if ((definedIds = this.declaredStuff.get(inclName)) != null) { @@ -755,8 +782,10 @@ protected boolean wasDefHandled(Root _root, String _id, boolean _setDefinedIfNot /** * Registers the declaration of entity {@code _id} as handled in the code for the {@link Root} * with signature {@code _signature}. Returns whether the - * @param _signature - * @param _id + * @param _signature - signature of the responsible {@link Root} + * @param _id - the identifier (or ':'-prefixed type key) of the declared entity + * @see #wasDefHandled(Root, String, boolean) + * @see #wasDefHandled(Root, String, boolean, boolean) */ protected void setDefHandled(String _signature, String _id) { StringList definedIds; @@ -1181,7 +1210,7 @@ protected String transform(String _input, boolean _doInputOutput) // but it's still needed for the meaningful ones. String[] keywords = CodeParser.getAllProperties(); for (int kw = 0; kw < keywords.length; kw++) - { + { if (keywords[kw].trim().length() > 0) { StringList keyTokens = this.splitKeywords.elementAt(kw); @@ -2791,6 +2820,14 @@ protected void appendCopyright(Root _root, String _indent, boolean _fullText) { this.appendComment("Copyright (C) " + _root.getCreatedString() + " " + _root.getAuthor(), _indent); if (_root.licenseName != null) { this.appendComment("License: " + _root.licenseName, _indent); + // START KGU#763 2019-11-13: Bugfix #778 + if (_fullText && _root.licenseText == null) { + String licText = this.loadLicenseText(_root.licenseName); + if (licText != null) { + this.appendComment(StringList.explode(licText, "\n"), _indent); + } + } + // END KGU#7763 2019-11-13 } if (_fullText && _root.licenseText != null) { this.appendComment(StringList.explode(_root.licenseText, "\n"), _indent); @@ -3784,6 +3821,58 @@ private void exportToStdOut() } } + // START KGU#763 2019-11-13: Fixes #778 (Missing license text on code export of "fresh" diagrams + /** + * Retrieves the licanes text associated to license name {@code licName} from + * the license pool directory + * @param licName - name of the license (file name will be drived from it) + * @return the text content of the license file (if existent), may be null + */ + protected String loadLicenseText(String licName) { + String error = null; + String content = ""; + File licDir = Ini.getIniDirectory(); + String licFileName = LicFilter.getNamePrefix() + licName + "." + LicFilter.acceptedExtension(); + File[] licFiles = licDir.listFiles(new LicFilter()); + File licFile = null; + for (int i = 0; licFile == null && i < licFiles.length; i++) { + if (licFileName.equalsIgnoreCase(licFiles[i].getName())) { + licFile = licFiles[i]; + } + } + BufferedReader br = null; + try { + InputStreamReader isr = new InputStreamReader(new FileInputStream(licFile), "UTF-8"); + br = new BufferedReader(isr); + String line = null; + while ((line = br.readLine()) != null) { + content += line + '\n'; + }; + } catch (UnsupportedEncodingException e) { + error = e.getMessage(); + } catch (FileNotFoundException e) { + error = e.getMessage(); + } catch (IOException e) { + error = e.getMessage(); + } + if (br != null) { + try { + br.close(); + } catch (IOException e) { + error = e.getMessage(); + } + } + if (error != null) { + getLogger().log(Level.WARNING, "{0}", error); + } + if (content.trim().isEmpty()) { + content = null; + } + return content; + } + // END KGU#763 2019-11-13 + + /******* FileFilter Extension *********/ protected boolean isOK(String _filename) { diff --git a/src/lu/fisch/structorizer/generators/JavaGenerator.java b/src/lu/fisch/structorizer/generators/JavaGenerator.java index dcb9d9f9..2204040f 100644 --- a/src/lu/fisch/structorizer/generators/JavaGenerator.java +++ b/src/lu/fisch/structorizer/generators/JavaGenerator.java @@ -75,6 +75,7 @@ * Kay Gürtzig 2019-03-30 Issue #696: Type retrieval had to consider an alternative pool * Kay Gürtzig 2019-10-02 Bugfix #755: Defective conversion of For-In loops with explicit array initializer * Kay Gürtzig 2019-10-03 Bugfix #755: Further provisional fixes for nested Array initializers + * Kay Gürtzig 2019-10-18 Enh. #739: Support for enum types (debugged on 2019-11-30) * ****************************************************************************************************** * @@ -254,6 +255,11 @@ protected String getIncludePattern() /************ Code Generation **************/ + // START KGU#542 2019-11-18: Enh. #739 - we need the current root for token transformation + /** Currently exported {@link Root} object */ + protected Root root = null; + // END KGU#542 2019-11-18 + // START KGU#560 2018-07-22 Bugfix #564 @Override protected boolean wantsSizeInArrayType() @@ -262,6 +268,12 @@ protected boolean wantsSizeInArrayType() } // END KGU#560 2018-07-22 + @Override + protected boolean arrayBracketsAtTypeName() + { + return true; + } + // START KGU#480 2018-01-21: Enh. #490 Improved support for Turtleizer export /** * Maps light-weight instances of DiagramControllers for API retrieval @@ -352,6 +364,9 @@ protected String transformTokens(StringList tokens) for (int i = 0; i < tokens.count(); i++) { String token = tokens.get(i); if (Function.testIdentifier(token, null)) { + // START KGU#542 2019-11-30: Enh. #739 - support for enum types + String constVal = null; // Will be needed on enum test + // END KGU#542 2019-11-30 int j = i; // Skip all whitespace while (j+2 < tokens.count() && tokens.get(++j).trim().isEmpty()); @@ -374,6 +389,16 @@ protected String transformTokens(StringList tokens) } } // END KGU#480 2018-01-21 + // START KGU#542 2019-11-18: Enh. #739 - support for enum types + else if (this.root != null && (constVal = this.root.constants.get(token)) != null) { + int posEu = constVal.indexOf('€'); + if (constVal.startsWith(":") && posEu > 1) { + // In general, the enum constant names are to be qualified + // (This is not true in case clause of switch instructions, however... + tokens.set(i, constVal.substring(1, posEu) + "." + token); + } + } + // END KGU#542 2019-11-18 } } return super.transformTokens(tokens); @@ -528,13 +553,14 @@ protected String transformRecordInit(String constValue, TypeMapEntry typeInfo) { // This is practically identical to C# // START KGU#559 2018-07-20: Enh. #563 - smarter record initialization //HashMap comps = Instruction.splitRecordInitializer(constValue); - HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo); + HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo, false); // END KGU#559 2018-07-20 LinkedHashMap compInfo = typeInfo.getComponentInfo(true); String recordInit = "new " + typeInfo.typeName + "("; boolean isFirst = true; for (Entry compEntry: compInfo.entrySet()) { String compName = compEntry.getKey(); + TypeMapEntry compType = compEntry.getValue(); String compVal = comps.get(compName); if (isFirst) { isFirst = false; @@ -546,12 +572,12 @@ protected String transformRecordInit(String constValue, TypeMapEntry typeInfo) { if (compVal == null) { recordInit += "null"; } - else if (compEntry.getValue().isRecord()) { - recordInit += transformRecordInit(compVal, compEntry.getValue()); + else if (compType != null && compType.isRecord()) { + recordInit += transformRecordInit(compVal, compType); } // START KGU#561 2018-07-21: Bugfix #564 - else if (compEntry.getValue().isArray() && compVal.startsWith("{") && compVal.endsWith("}")) { - String elemType = compEntry.getValue().getCanonicalType(true, false).substring(1); + else if (compType != null && compType.isArray() && compVal.startsWith("{") && compVal.endsWith("}")) { + String elemType = compType.getCanonicalType(true, false).substring(1); recordInit += "new " + this.transformType(elemType, "object") + "[]" + compVal; } // END KGU#561 2018-07-21 @@ -674,6 +700,26 @@ protected void generateTypeDef(Root _root, String _typeName, TypeMapEntry _type, addCode("}", indentPlus1, _asComment); addCode("};", _indent, _asComment); } + // START KGU#542 2019-11-17: Enh. #739 + else if (_type.isEnum()) { + String indentPlus1 = subroutineIndent; + String indentPlus2 = indentPlus1 + this.getIndent(); + StringList items = _type.getEnumerationInfo(); + String itemList = items.concatenate(", "); + if (itemList.length() > 70) { + this.insertCode(indentPlus1 + "private enum " + _type.typeName + " {", subroutineInsertionLine++); + for (int i = 0; i < items.count(); i++) { + // FIXME: We might have to transform the value... + insertCode(indentPlus2 + items.get(i) + (i < items.count() -1 ? "," : ""), subroutineInsertionLine++); + } + insertCode(indentPlus1 + "};", subroutineInsertionLine++); + } + else { + insertCode(indentPlus1 + "private enum " + _type.typeName + "{" + itemList + "};", subroutineInsertionLine++); + } + insertCode("", subroutineInsertionLine++); + } + // END KGU#542 2019-11-17 else { // FIXME: What do we here in Java? Replace this type name all over the code? addCode("typedef " + this.transformTypeFromEntry(_type, null) + " " + _typeName + ";", @@ -1020,11 +1066,14 @@ private StringList makeArgList(StringList varNames, HashMap comps = Instruction.splitRecordInitializer(constValue); - HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo); + // START KGU#771 2019 11-24: Bugfix #783 - precaution against unknown type + //HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo); + HashMap comps = Instruction.splitRecordInitializer(constValue, typeInfo, true); + // END KGU#771 2019-11-24 // END KGU#559 2018-07-20 LinkedHashMap compInfo; if (typeInfo != null) { @@ -215,6 +219,7 @@ protected String transformRecordInit(String constValue, TypeMapEntry typeInfo) { for (Entry compEntry: compInfo.entrySet()) { String compName = compEntry.getKey(); String compVal = comps.get(compName); + TypeMapEntry compType = compEntry.getValue(); if (!compName.startsWith("§") && compVal != null) { if (isFirst) { isFirst = false; @@ -223,11 +228,14 @@ protected String transformRecordInit(String constValue, TypeMapEntry typeInfo) { recordInit.append(", "); } recordInit.append(compName + ":"); - if (compEntry.getValue() != null && compEntry.getValue().isRecord()) { - recordInit.append(transformRecordInit(compVal, compEntry.getValue())); + if (compType != null && compType.isRecord()) { + recordInit.append(transformRecordInit(compVal, compType)); } // START KGU#732 2019-10-03: Bugfix #755 FIXME - nasty workaround - else if (compEntry.getValue().isArray() && compVal.startsWith("{") && compVal.endsWith("}")) { + // START KGU#771 2019-11-24: Bugfix #783 Caused a NullPointer exception on missing type info + //else if (compType.isArray() && compVal.startsWith("{") && compVal.endsWith("}")) { + else if (compType != null && compType.isArray() && compVal.startsWith("{") && compVal.endsWith("}")) { + // END KGU#771 2019-11-24 StringList items = Element.splitExpressionList(compVal.substring(1), ",", true); items.delete(items.count()-1); for (int i = 0; i < items.count(); i++) { @@ -492,7 +500,7 @@ protected void appendDeclaration(Root _root, String _name, String _indent, boole if (wasDefHandled(_root, _name, false)) { return; } - String constValue = _root.constants.get(_name); + String constValue = _root.getConstValueString(_name); String decl = "var " + _name; if (_root.constants.containsKey(_name) && constValue != null) { decl = "const " + _name; diff --git a/src/lu/fisch/structorizer/generators/KSHGenerator.java b/src/lu/fisch/structorizer/generators/KSHGenerator.java index 4492c0e1..1a85dc54 100644 --- a/src/lu/fisch/structorizer/generators/KSHGenerator.java +++ b/src/lu/fisch/structorizer/generators/KSHGenerator.java @@ -52,7 +52,8 @@ * Kay Gürtzig 2017-05-16 Enh. #372: Export of copyright information * Kay Gürtzig 2019-03-08 Enh. #385: Optional function arguments with defaults * Kay Gürtzig 2019-09-27 Enh. #738: Support for code preview map on Root level - * Kay Gürttig 2019-10-15 Bugfix #765: Field typeMap had to be initialized, e.g. for transformTokens + * Kay Gürtzig 2019-10-15 Bugfix #765: Field typeMap had to be initialized, e.g. for transformTokens() + * Kay Gürtzig 2019-12-01 Enh. #739: At least minimum support for enum types, array declarations mended * ****************************************************************************************************** * @@ -64,9 +65,11 @@ * ******************************************************************************************************/// +import java.util.Map.Entry; import lu.fisch.structorizer.elements.Element; import lu.fisch.structorizer.elements.Root; +import lu.fisch.structorizer.elements.TypeMapEntry; import lu.fisch.utils.StringList; @@ -104,7 +107,38 @@ protected String commentSymbolLeft() /************ Code Generation **************/ -// // START KGU 2016-01-08: Possible replacement (portable shell code) for the inherited modern BASH code + // START KGU#542 2019-12-01: Enh. #739 enumeration type support - configuration for subclasses + /* (non-Javadoc) + * @see lu.fisch.structorizer.generators.BASHGenerator#getEnumDeclarator() + */ + @Override + protected String getEnumDeclarator() + { + return ""; // ksh doesn't know a declare command (as far as we know) + } + + // On this occasion, we also repair the array declaration, which differes from bash + /* (non-Javadoc) + * @see lu.fisch.structorizer.generators.BASHGenerator#getArrayDeclarator() + */ + @Override + protected String getArrayDeclarator() + { + return "set -A "; + } + + /* (non-Javadoc) + * @see lu.fisch.structorizer.generators.BASHGenerator#getAssocDeclarator() + */ + @Override + protected String getAssocDeclarator() + { + return "typeset -A "; + } + // END KGU#542 2019-12-01 + + + // // START KGU 2016-01-08: Possible replacement (portable shell code) for the inherited modern BASH code // @Override // protected void generateCode(For _for, String _indent) { // @@ -236,6 +270,14 @@ public String generateCode(Root _root, String _indent) { // END KGU#53 2015-11-02 } + // START KGU#542 2019-12-01: Enh. #739 - support for enumeration types + for (Entry typeEntry: typeMap.entrySet()) { + TypeMapEntry type = typeEntry.getValue(); + if (typeEntry.getKey().startsWith(":") && type != null && type.isEnum()) { + appendEnumeratorDef(type, _indent); + } + } + // END KGU#542 2019-12-01 // START KGU#129 2016-01-08: Bugfix #96 - Now fetch all variable names from the entire diagram varNames = _root.retrieveVarNames(); appendComment("TODO: Check and revise the syntax of all expressions!", _indent); diff --git a/src/lu/fisch/structorizer/generators/OberonGenerator.java b/src/lu/fisch/structorizer/generators/OberonGenerator.java index 413d459e..306b5747 100644 --- a/src/lu/fisch/structorizer/generators/OberonGenerator.java +++ b/src/lu/fisch/structorizer/generators/OberonGenerator.java @@ -77,6 +77,12 @@ * Kay Gürtzig 2019-03-30 Issue #696: Type retrieval had to consider an alternative pool * Kay Gürtzig 2019-11-11 Bugfix #773: Mere declarations at top level exported, declarations * with incomplete type no longer outcommented but marked with FIXME! comments + * Kay Gürtzig 2019-11-12 Enh. #775: Slightly more type-sensitive input instruction handling + * Kay Gürtzig 2019-11-13 Bugfix #776: Mere global declarations (from includables must not be repeated + * as local declarations in subroutines where the variables get assigned + * Kay Gürtzig 2019-11-14 Bugfix #779 Correct handling of input and output in case of program diagrams + * Kay Gürtzig 2019-11-14 Issue #780: Definitions and calls of parameterless procedures omit parentheses + * Kay Gürtzig 2019-11-21 Enh. #739: enum type inference for FOR-IN loops and output * ****************************************************************************************************** * @@ -525,16 +531,22 @@ protected void generateCode(Instruction _inst, String _indent) if (!prompt.isEmpty()) { generateTypeSpecificOutput(prompt, _indent, isDisabled, outputKey); } - appendComment("TODO: Replace \"TYPE\" by the the actual In procedure name for the respective type!", _indent); + //appendComment("TODO: Replace \"TYPE\" by the the actual In procedure name for the respective type!", _indent); for (int j = 1; j < inputItems.count(); j++) { String inputItem = inputItems.get(j); - addCode(transform(inputKey + " \"" + inputItem + "\" " + inputItem), _indent, isDisabled); + // START KGU#761 2019-11-12: Enh. #775 - slightly more intelligence is feasible here + //addCode(transform(inputKey + " \"" + inputItem + "\" " + inputItem), _indent, isDisabled); + addCode(specifyInputMethod(_indent, inputItem, transform(inputKey + " \"" + inputItem + "\" " + inputItem)), _indent, isDisabled); + // END KGU#761 2019-11-12 } } else { String transf = transform(line).replace("In.TYPE()", "In.Char(dummyInputChar)") + ";"; if (transf.contains("In.TYPE(")) { - appendComment("TODO: Replace \"TYPE\" by the the actual In procedure name for this type!", _indent); + // START KGU#761 2019-11-12: Enh. #775 - slightly more intelligence is feasible here + //appendComment("TODO: Replace \"TYPE\" by the the actual In procedure name for this type!", _indent); + transf = specifyInputMethod(_indent, inputItems.get(1), transf); + // END KGU#761 2019-11-12 } addCode(transf, _indent, isDisabled); } @@ -654,6 +666,50 @@ else if (bracePos > 0 && expr.endsWith("}") } // END KGU 2015-10-18 } + + // START KGU#761 2019-11-12: Enh. #775 - slightly more intelligence is feasible here + /** + * Tries to replace the placeholder `TYPE' in the transformed default input phrase {@code transf} + * by a type-specific actual method name for the type of the variable given by {@code varName}. + * @param _indent - current indentation level + * @param varName - input variable string (might of course be an array element or a record component) + * @param transf - the general transformed input instruction, presumably with placeholder "In.TYPE(..." + * @return a revised (and more specific) input instruction + */ + private String specifyInputMethod(String _indent, String varName, String transf) { + boolean done = false; + TypeMapEntry type = this.typeMap.get(varName); + if (type != null) { + String typeName = type.getCanonicalType(true, true); + if (typeName != null && !typeName.trim().isEmpty() && !typeName.contains("???")) { + typeName = this.transformType(typeName, "TYPE"); + done = true; + if (typeName.equals("INTEGER") || typeName.equals("SHORTINT")) { + transf = transf.replace("In.TYPE(", "In.Int("); + } + else if (typeName.equals("LONGINT")) { + transf = transf.replace("In.TYPE(", "In.LongInt("); + } + else if (typeName.equals("CHAR")) { + transf = transf.replace("In.TYPE(", "In.Char("); + } + else if (typeName.endsWith("REAL")) { + transf = transf.replace("In.TYPE(", "In.Real("); + } + else if (typeName.equals("ARRAY 100 OF CHAR")) { + transf = transf.replace("In.TYPE(", "In.String("); + } + else { + done = false; + } + } + } + if (!done) { + appendComment("TODO: Replace \"TYPE\" by the the actual In procedure name for this type!", _indent); + } + return transf; + } + // END KGU#761 2019-11-12 // START KGU#236 2016-10-15: Issue #227 - For literals, we can of course determine the type... /** @@ -710,7 +766,10 @@ protected void generateTypeSpecificOutput(String _expression, String _indent, bo StringList types = this.getTransformedTypes(typeInfo, false); if (types.count() == 1) { String type = types.get(0); - if (type.equals("INTEGER") || type.equals("LONGINT") || type.equals("SHORTINT")) { + // START KGU#542 2019-11-21: Enh. #739 - also accept enum type here + //if (type.equals("INTEGER") || type.equals("LONGINT") || type.equals("SHORTINT")) { + if (typeInfo.isEnum() || type.equals("INTEGER") || type.equals("LONGINT") || type.equals("SHORTINT")) { + // END KGU#542 2019-11-231 procName = "Int"; length = ", 10"; } @@ -781,7 +840,7 @@ private void generateRecordInit(String _varName, String _expr, String _indent, b { // START KGU#559 2018-07-22: Enh. #563 //HashMap components = Instruction.splitRecordInitializer(_expr); - HashMap components = Instruction.splitRecordInitializer(_expr, _recType); + HashMap components = Instruction.splitRecordInitializer(_expr, _recType, false); // END KGU#559 2018-07-22 if (_forConstant) { appendComment("Note: " + _varName + " was meant to be a record CONSTANT...", _indent); @@ -951,10 +1010,13 @@ protected boolean generateForInCode(For _for, String _indent) if (items != null) { // Good question is: how do we guess the element type and what do we - // do if items are heterogenous? We will just try four types: boolean, - // integer, real and string, where we can only test literals. + // do if items are heterogenous? We will just try five types: boolean, + // common enum type, integer, real and string, where we can only test literals. // If none of them match then we add a TODO comment. int nItems = items.count(); + // START KGU#542 2019-11-21: Enh. #739 + String allEnum = ""; + // END KGU#542 2019-11-21 boolean allBoolean = true; boolean allInt = true; boolean allReal = true; @@ -962,6 +1024,9 @@ protected boolean generateForInCode(For _for, String _indent) for (int i = 0; i < nItems; i++) { String item = items.get(i); + // START KGU#542 2019-11-21: Enh. #739 + TypeMapEntry tme = this.typeMap.get(item); + // END KGU#542 2019-11-21 if (allBoolean) { if (!item.equalsIgnoreCase("true") && !item.equalsIgnoreCase("false")) @@ -976,7 +1041,10 @@ protected boolean generateForInCode(For _for, String _indent) } catch (NumberFormatException ex) { - allInt = false; + // START KGU#542 2019-11-21: Enh. #739 enum type support - it might be an enumerator constant + //allInt = false; + allInt = tme != null && tme.isEnum(); + // END KGU#542 2019-11-21 } } if (allReal) @@ -996,9 +1064,29 @@ protected boolean generateForInCode(For _for, String _indent) item.startsWith("\'") && item.endsWith("\'") && !item.substring(1, item.length()-1).contains("\'"); } + // START KGU#542 2019-11-21: Enh. #739 support for enumerator types + if (allEnum != null) + { + if (tme != null && tme.isEnum()) { + if (allEnum.isEmpty()) { + allEnum = tme.typeName; + } + else if (!allEnum.equals(tme.typeName)) { + allEnum = null; // Game over for enumerator (different enumerators) + } + } + else { + // Obviously no enumerator constant + allEnum = null; + } + } + // END KGU#542 2019-11-21 } if (allBoolean) itemType = "BOOLEAN"; + // START KGU#542 2019-11-21: Enh. #739 + else if (allEnum != null && !allEnum.isEmpty()) itemType = allEnum; + // END KGU#542 2019-11-21 else if (allInt) itemType = "INTEGER"; else if (allReal) itemType = "REAL"; else if (allString) itemType = "ARRAY 100 OF CHAR"; @@ -1113,6 +1201,9 @@ protected void generateCode(Call _call, String _indent) // START KGU#371 2019-03-08: Enh. #385 Support for declared optional arguments //addCode(transform(lines.get(i))+";", _indent, isDisabled); String line = lines.get(i); + // START KGU#766 2019-11-14: Issue #780 Omit empty parentheses on procedure calls. + boolean isFctCall = Instruction.isAssignment(line); + // END KGU#766 2019-11-14 if (i == 0 && this.getOverloadingLevel() == OverloadingLevel.OL_NO_OVERLOADING && (routinePool != null) && line.endsWith(")")) { Function call = _call.getCalledRoutine(); java.util.Vector callCandidates = routinePool.findRoutinesBySignature(call.getName(), call.paramCount(), owningRoot); @@ -1126,8 +1217,18 @@ protected void generateCode(Call _call, String _indent) line = line.substring(0, line.length()-1) + (call.paramCount() > 0 ? ", " : "") + defaults.subSequence(call.paramCount(), defaults.count()).concatenate(", ") + ")"; } + // START KGU#766 2019-11-14: Issue #780 Check if it might yet be a function + if (called.getResultType() != null) { + isFctCall = true; + } + // END KGU#766 2019-11-14 } } + // START KGU#766 2019-11-14: Issue #780 Omit empty parentheses on procedure calls. + if (!isFctCall && line.endsWith("()")) { + line = line.substring(0, line.length()-2); + } + // END KGU#766 2019-11-14 addCode(transform(line)+";", _indent, isDisabled); // END KGU#371 2019-03-08 } @@ -1274,8 +1375,13 @@ protected void generateCode(Parallel _para, String _indent) protected String generateHeader(Root _root, String _indent, String _procName, StringList _paramNames, StringList _paramTypes, String _resultType) { - // FIXME: How to handle includable diagrams? String header = (_root.isProgram() ? "MODULE " : "PROCEDURE ") + _procName; + // START KGU#765 2019-11-14: Enh. 346, bugfix #779 Avoid duplicate IMPORTs + if (topLevel) { + if (this.hasInput()) generatorIncludes.add("In"); + if (this.hasOutput()) generatorIncludes.add("Out"); + } + // END KGU#765 2019-11-14 if (!_root.isProgram()) { // FIXME: How to handle includable diagrams? @@ -1300,7 +1406,7 @@ protected String generateHeader(Root _root, String _indent, String _procName, code.add(_indent + "MODULE " + moduleName + ";"); code.add(_indent); - // STARTB KGU#351 2017-02-26: Enh. #346 + // START KGU#351 2017-02-26: Enh. #346 this.appendUserIncludes(_indent); // END KGU#351 2017-02-26 if (this.hasInput() || this.hasOutput()) @@ -1325,7 +1431,8 @@ protected String generateHeader(Root _root, String _indent, String _procName, header += "*"; // Marked for export as default String lastType = ""; - header += "("; + //header += "("; + String paramList = ""; int nParams = _paramNames.count(); for (int p = 0; p < nParams; p++) { String type = transformType(_paramTypes.get(p), "(*type?*)"); @@ -1337,29 +1444,30 @@ protected String generateHeader(Root _root, String _indent, String _procName, if (p > 0) { if (type.equals("(*type?*)") || !type.equals(lastType)) { // END KGU#140 2017-01-31 - header += ": " + lastType + "; "; + paramList += ": " + lastType + "; "; // START KGU#332 2017-01-31: Enh. #335 Improved type support if (type.contains("ARRAY") && !_paramNames.get(p).trim().startsWith("VAR ")) { - header += "VAR "; + paramList += "VAR "; } // END KGU#332 2017-01-31 } else { - header += ", "; + paramList += ", "; } // START KGU#140 2017-01-31; Enh. #113 - array conversion in argument list } // END KGU#140 2017-01-31 - header += _paramNames.get(p).trim(); + paramList += _paramNames.get(p).trim(); if (p+1 == nParams) { //header += ": " + type + ")"; - header += ": " + type; + paramList += ": " + type; } lastType = type; } - header += ")"; + //header += ")"; if (_resultType != null || this.returns || this.isFunctionNameSet || this.isResultSet) { + header += "(" + paramList + ")"; // START KGU#332 2017-01-31: Enh. #335 //header += ": " + transformType(_resultType, ""); String oberonType = transformType(_resultType, ""); @@ -1369,6 +1477,9 @@ protected String generateHeader(Root _root, String _indent, String _procName, header += ": " + oberonType; // END KGI#332 2017-01-31 } + else if (!paramList.isEmpty()) { + header += "(" + paramList + ")"; + } } code.add(_indent + header + ";"); @@ -1378,13 +1489,25 @@ protected String generateHeader(Root _root, String _indent, String _procName, //{ // code.add(_indent + "IMPORT In, Out"); // Later, this could be done on demand //} - if (_root.isProgram() && (this.hasInput(_root) || this.hasOutput(_root))) + // START KGU#765 2019-11-14: Bugfix #779 + //if (_root.isProgram() && (this.hasInput(_root) || this.hasOutput(_root))) + //{ + // StringList ioModules = new StringList(); + // if (this.hasInput(_root)) ioModules.add("In"); + // if (this.hasOutput(_root)) ioModules.add("Out"); + // code.add(_indent + "IMPORT " + ioModules.concatenate(", ") + ";"); + //} + if (_root.isProgram()) { - StringList ioModules = new StringList(); - if (this.hasInput(_root)) ioModules.add("In"); - if (this.hasOutput(_root)) ioModules.add("Out"); - code.add(_indent + "IMPORT " + ioModules.concatenate(", ") + ";"); + this.appendUserIncludes(_indent); + if (this.hasInput() || this.hasOutput()) { + StringList ioModules = new StringList(); + if (this.hasInput()) ioModules.add("In"); + if (this.hasOutput()) ioModules.add("Out"); + code.add(_indent + "IMPORT " + ioModules.concatenate(", ") + ";"); + } } + // END KGU#765 2019-11-14 // END KGU#236 2016-08-10 // END KGU#61 2016-03-23 @@ -1480,11 +1603,17 @@ protected String generatePreamble(Root _root, String _indent, StringList varName code.add(_indent + "BEGIN"); // START KGU#236 2016-08-10: Issue #227 boolean isProcModule = _root.isSubroutine() && this.optionExportSubroutines(); - if (topLevel && this.hasInput(_root) && !isProcModule) + // START KGU#765 2019-11-14: Bugfix #779 + //if (topLevel && this.hasInput(_root) && !isProcModule) + if (topLevel && this.hasInput() && !isProcModule) + // END KGU#765 2019-11-14 { code.add(_indent + this.getIndent() + "In.Open;"); } - if (topLevel && this.hasOutput(_root) && !isProcModule) + // START KGU#765 2019-11-14: Bugfix #779 + //if (topLevel && this.hasOutput(_root) && !isProcModule) + if (topLevel && this.hasOutput() && !isProcModule) + // END KGU#765 2019-11-14 { code.add(_indent + this.getIndent() + "Out.Open;"); // This is optional, actually } @@ -1576,6 +1705,8 @@ protected Root[] generateDeclarations(Root _root, String _indent, StringList _va } introPlaced = false; // Has the TYPE keyword already been written? + // We must not repeat global declaration on local level, the loop won't be executed on sub-levels + // because `includes' was only filled at top level (see above) for (Root incl: includes) { if (incl != _root) { introPlaced = generateVarDecls(incl, _indent, incl.retrieveVarNames(), _complexConsts, introPlaced); @@ -1585,18 +1716,29 @@ protected Root[] generateDeclarations(Root _root, String _indent, StringList _va //if (_varNames != null) { if (_varNames != null && (!this.suppressTransformation || _root.isInclude())) { // END KGU#504 2018-03-13 - introPlaced = generateVarDecls(_root, _indent, _varNames, _complexConsts, introPlaced); + // START KGU#762 2019-11-13: Bugfix #776 - we must not repeat mere decalartions from Includables here + //introPlaced = generateVarDecls(_root, _indent, _varNames, _complexConsts, introPlaced); + StringList ownVarNames = _varNames.copy(); + if (!topLevel && _root.includeList != null) { + for (Root incl: includedRoots) { + // Because of recursiveness of declaration retrieval, we may restrict to the + // directly included diagrams, this reduces the risk of eliminating variable + // names that are not included but locally defined. + if (_root.includeList.contains(incl.getMethodName())) { + StringList declNames = incl.getMereDeclarationNames(); + for (int i = 0; i < declNames.count(); i++) { + ownVarNames.removeAll(declNames.get(i)); + } + } + } + } + introPlaced = generateVarDecls(_root, _indent, ownVarNames, _complexConsts, introPlaced); + // END KGU#762 2019-11-13 } // END KGU#375 2017-04-12 - // START KGU#759 2019-11-11: Bugfix #733 - Specific care for merely declared (uninitialized) variables + // START KGU#759 2019-11-11: Bugfix #773 - Specific care for merely declared (uninitialized) variables if (topLevel) { - StringList declNames = new StringList(); // Names of declared variables without initialisations - for (String id: this.typeMap.keySet()) { - if (!id.startsWith(":") && !_varNames.contains(id)) { - declNames.add(id); - } - } - generateVarDecls(_root, _indent, declNames, new StringList(), introPlaced); + generateVarDecls(_root, _indent, _root.getMereDeclarationNames(), new StringList(), introPlaced); } // END KGU#759 2019-11-11 return includes; @@ -1622,7 +1764,14 @@ protected boolean generateConstDefs(Root _root, String _indent, StringList _comp if (wasDefHandled(_root, constName, true)) { continue; } - String expr = transform(constEntry.getValue()); + // START KGU#452 2019-11-17: Enh. #739 Skip enumerator values - they are to be handled in a type definition + //String expr = transform(constEntry.getValue()); + String expr = constEntry.getValue(); + if (expr != null && expr.startsWith(":")) { + continue; + } + expr = transform(expr); + // END KGU#452 2019-11-17 // START KGU#676 2019-03-30: Enh. #696 special pool in case of batch export //TypeMapEntry constType = _root.getTypeInfo().get(constEntry.getKey()); TypeMapEntry constType = _root.getTypeInfo(routinePool).get(constEntry.getKey()); @@ -1685,6 +1834,17 @@ protected boolean generateTypeDefs(Root _root, String _indent, boolean _sectionB } code.add(indentPlus2 + "END;"); } + // START KGU#542 2019-11-17: Enh. #739 + else if (type.isEnum()) { + code.add(indentPlus1 + key.substring(1) + " = ENUM"); + StringList items = type.getEnumerationInfo(); + for (int i = 0; i < items.count(); i++) { + // FIXME: We might have to transform the value... + code.add(indentPlus3 + items.get(i) + (i < items.count()-1 ? "," : "")); + } + code.add(indentPlus2 + "END;"); + } + // END KGU#542 2019-11-17 else { code.add(indentPlus1 + key.substring(1) + " = " + this.transformTypeFromEntry(type, null) + ";"); } @@ -1760,7 +1920,7 @@ protected boolean generateVarDecls(Root _root, String _indent, StringList _varNa //} } else { - // START KGU#759 2019-11-11: Issue #733 - it only irritates the user to outcomment this - the code isn't compilable anyway + // START KGU#759 2019-11-11: Issue #773 - it only irritates the user to outcomment this - the code isn't compilable anyway //appendComment(varName + ": ???;", indentPlus1); addCode(varName + ": ???;\t" + this.commentSymbolLeft() + " FIXME! " + this.commentSymbolRight(), indentPlus1, false); // END KGU#759 2019-11-11 diff --git a/src/lu/fisch/structorizer/generators/PasGenerator.java b/src/lu/fisch/structorizer/generators/PasGenerator.java index 4bb07b8d..4a23034e 100644 --- a/src/lu/fisch/structorizer/generators/PasGenerator.java +++ b/src/lu/fisch/structorizer/generators/PasGenerator.java @@ -84,6 +84,10 @@ * Kay Gürtzig 2019-11-08 Bugfix #772: NullPointerExceptions in code preview, due to late typeMap init * Kay Gürtzig 2019-11-11 Bugfix #773: Mere declarations at top level exported, incomplete * declarations (defective type) no longer as comment but with FIXME! marker + * Kay Gürtzig 2019-11-13 Bugfix #776: Mere global declarations (from includables must not be repeated + * as local declarations in subroutines where the variables get assigned + * Kay Gürtzig 2019-11-21 Enh. #739: enum type inference for FOR-IN loops + * Kay Gürtzig 2019-11-29 Bugfix 787: multiple global type definitions (as many times as includables involved) * ****************************************************************************************************** * @@ -331,7 +335,7 @@ protected String transformArrayDeclaration(String _typeDescr) { if (_typeDescr.toLowerCase().startsWith("array") || _typeDescr.endsWith("]")) { // TypeMapEntries are really good at analysing array definitions - TypeMapEntry typeInfo = new TypeMapEntry(_typeDescr, null, null, null, 0, false, true, false); + TypeMapEntry typeInfo = new TypeMapEntry(_typeDescr, null, null, null, 0, false, true); _typeDescr = transformTypeFromEntry(typeInfo, null); } return _typeDescr; @@ -755,7 +759,7 @@ private void generateArrayInit(String _varName, String _expr, String _indent, St // HashMap components = Instruction.splitRecordInitializer(_expr); private void generateRecordInit(String _varName, String _expr, String _indent, boolean _forConstant, boolean _isDisabled, TypeMapEntry _typeEntry) { - HashMap components = Instruction.splitRecordInitializer(_expr, _typeEntry); + HashMap components = Instruction.splitRecordInitializer(_expr, _typeEntry, false); // END KGU#559 2018-07-20 if (_forConstant) { String typeName = components.get("§TYPENAME§"); @@ -978,10 +982,13 @@ protected boolean generateForInCode(For _for, String _indent) if (items != null) { // Good question is: how do we guess the element type and what do we - // do if items are heterogenous? We will just try four types: boolean, - // integer, real and string, where we can only test literals. + // do if items are heterogenous? We will just try five types: boolean, + // common enum type, integer, real and string, where we can only test literals. // If none of them match then we add a TODO comment. int nItems = items.count(); + // START KGU#542 2019-11-21: Enh. #739 + String allEnum = ""; + // END KGU#542 2019-11-21 boolean allBoolean = true; boolean allInt = true; boolean allReal = true; @@ -989,6 +996,9 @@ protected boolean generateForInCode(For _for, String _indent) for (int i = 0; i < nItems; i++) { String item = items.get(i); + // START KGU#542 2019-11-21: Enh. #739 + TypeMapEntry tme = this.typeMap.get(item); + // END KGU#542 2019-11-21 if (allBoolean) { if (!item.equalsIgnoreCase("true") && !item.equalsIgnoreCase("false")) @@ -1003,7 +1013,10 @@ protected boolean generateForInCode(For _for, String _indent) } catch (NumberFormatException ex) { - allInt = false; + // START KGU#542 2019-11-21: Enh. #739 enum type support - it might be an enumerator constant + //allInt = false; + allInt = tme != null && tme.isEnum(); + // END KGU#542 2019-11-21 } } if (allReal) @@ -1023,6 +1036,23 @@ protected boolean generateForInCode(For _for, String _indent) item.startsWith("\'") && item.endsWith("\'") && !item.substring(1, item.length()-1).contains("\'"); } + // START KGU#542 2019-11-21: Enh. #739 support for enumerator types + if (allEnum != null) + { + if (tme != null && tme.isEnum()) { + if (allEnum.isEmpty()) { + allEnum = tme.typeName; + } + else if (!allEnum.equals(tme.typeName)) { + allEnum = null; // Game over for enumerator (different enumerators) + } + } + else { + // Obviously no enumerator constant + allEnum = null; + } + } + // END KGU#542 2019-11-21 } // Create some generic and unique variable names @@ -1032,6 +1062,9 @@ protected boolean generateForInCode(For _for, String _indent) String itemType = ""; if (allBoolean) itemType = "boolean"; + // START KGU#542 2019-11-21: Enh. #739 + else if (allEnum != null && !allEnum.isEmpty()) itemType = allEnum; + // END KGU#542 2019-11-21 else if (allInt) itemType = "integer"; else if (allReal) itemType = "real"; else if (allString) itemType = "string"; @@ -1686,18 +1719,29 @@ protected Root[] generateDeclarations(Root _root, String _indent, StringList _va //if (_varNames != null) { if (_varNames != null && (!this.suppressTransformation || _root.isInclude())) { // END KGU#504 2018-03-13 - introPlaced = generateVarDecls(_root, _indent, _varNames, _complexConsts, introPlaced); + // START KGU#762 2019-11-13: Bugfix #776 - we must not repeat mere decalartions from Includables here + //introPlaced = generateVarDecls(_root, _indent, _varNames, _complexConsts, introPlaced); + StringList ownVarNames = _varNames.copy(); + if (!topLevel && _root.includeList != null) { + for (Root incl: includedRoots) { + // Because of recursiveness of declaration retrieval, we may restrict to the + // directly included diagrams, this reduces the risk of eliminating variable + // names that are not included but locally defined. + if (_root.includeList.contains(incl.getMethodName())) { + StringList declNames = incl.getMereDeclarationNames(); + for (int i = 0; i < declNames.count(); i++) { + ownVarNames.removeAll(declNames.get(i)); + } + } + } + } + introPlaced = generateVarDecls(_root, _indent, ownVarNames, _complexConsts, introPlaced); + // END KGU#762 2019-11-13 } // END KGU#375 2017-04-12 - // START KGU#759 2019-11-11: Bugfix #733 - Specific care for merely declared (uninitialized) variables + // START KGU#759 2019-11-11: Bugfix #773 - Specific care for merely declared (uninitialized) variables if (topLevel) { - StringList declNames = new StringList(); // Names of declared variables without initialisations - for (String id: this.typeMap.keySet()) { - if (!id.startsWith(":") && !_varNames.contains(id)) { - declNames.add(id); - } - } - generateVarDecls(_root, _indent, declNames, new StringList(), introPlaced); + generateVarDecls(_root, _indent, _root.getMereDeclarationNames(), new StringList(), introPlaced); } // END KGU#759 2019-11-11 return includes; @@ -1725,7 +1769,15 @@ protected boolean generateConstDefs(Root _root, String _indent, StringList _comp } // START KGU#388 2017-09-19: Enh. #423 Modern Pascal allows structured constants //code.add(indentPlus1 + constEntry.getKey() + " = " + transform(constEntry.getValue()) + ";"); - String expr = transform(constEntry.getValue()); + // START KGU#452 2019-11-17: Enh. #739 Skip enumerator values - they are to be handled in a type definition + //String expr = transform(constEntry.getValue()); + //String expr = transform(constEntry.getValue()); + String expr = constEntry.getValue(); + if (expr != null && expr.startsWith(":")) { + continue; + } + expr = transform(expr); + // END KGU#452 2019-11-17 TypeMapEntry constType = typeMap.get(constEntry.getKey()); if (constType == null || (!constType.isArray() && !constType.isRecord())) { if (!_sectionBegun) { @@ -1789,7 +1841,10 @@ protected boolean generateTypeDefs(Root _root, String _indent, boolean _sectionB String indentPlus1 = _indent + this.getIndent(); String indentPlus2 = indentPlus1 + this.getIndent(); String indentPlus3 = indentPlus2 + this.getIndent(); - for (Entry typeEntry: typeMap.entrySet()) { + // START KGU#774 2019-11-29: Bugfix #787 - On top level, any Includable declared any types known to main + //for (Entry typeEntry: typeMap.entrySet()) { + for (Entry typeEntry: _root.getTypeInfo(routinePool).entrySet()) { + // END KGU#774 2019-11-29 String key = typeEntry.getKey(); if (key.startsWith(":") /*&& typeEntry.getValue().isDeclaredWithin(_root)*/) { if (wasDefHandled(_root, key, true)) { @@ -1810,6 +1865,23 @@ protected boolean generateTypeDefs(Root _root, String _indent, boolean _sectionB } code.add(indentPlus2 + "END;"); } + // START KGU#542 2019-11-17: Enh. #739 + else if (type.isEnum()) { + StringList items = type.getEnumerationInfo(); + String itemList = items.concatenate(", "); + if (itemList.length() > 70) { + code.add(indentPlus1 + key.substring(1) + " = ("); + for (int i = 0; i < items.count(); i++) { + // FIXME: We might have to transform the value... + code.add(indentPlus3 + items.get(i) + (i < items.count()-1 ? "," : "")); + } + code.add(indentPlus2 + ");"); + } + else { + code.add(indentPlus1 + key.substring(1) + " = (" + itemList + ");"); + } + } + // END KGU#542 2019-11-17 else { code.add(indentPlus1 + key.substring(1) + " = " + this.transformTypeFromEntry(type, null) + ";"); } @@ -1893,10 +1965,10 @@ protected boolean generateVarDecls(Root _root, String _indent, StringList _varNa type = prefix + type; String comment = ""; if (type.contains("???")) { - // START KGU#759 2019-11-11: Issue #733 - it only irritates the user to outcomment this - the code isn't compilable anyway - appendComment(varName + ": " + type + ";", indentPlus1); + // START KGU#759 2019-12-02: Issue #773 - it only irritates the user to outcomment this - the code isn't compilable anyway + //appendComment(varName + ": " + type + ";", indentPlus1); comment = "\t" + this.commentSymbolLeft() + " FIXME! " + this.commentSymbolRight(); - // END KGU#759 2019-11-11 + // END KGU#759 2019-12-02 } //else { if (isComplexConst) { @@ -1906,7 +1978,7 @@ protected boolean generateVarDecls(Root _root, String _indent, StringList _varNa //} } else { - // START KGU#759 2019-11-11: Issue #733 - it only irritates the user to outcomment this - the code isn't compilable anyway + // START KGU#759 2019-11-11: Issue #773 - it only irritates the user to outcomment this - the code isn't compilable anyway //appendComment(varName, indentPlus1); addCode(varName + ": ???;\t" + this.commentSymbolLeft() + " FIXME! " + this.commentSymbolRight(), indentPlus1, false); // END KGU#759 2019-11-11 diff --git a/src/lu/fisch/structorizer/generators/PerlGenerator.java b/src/lu/fisch/structorizer/generators/PerlGenerator.java index 8c3ec989..93be7d23 100644 --- a/src/lu/fisch/structorizer/generators/PerlGenerator.java +++ b/src/lu/fisch/structorizer/generators/PerlGenerator.java @@ -77,16 +77,24 @@ * Kay Gürtzig 2019-03-08 Enh. #385: Support for parameter default values * Kay Gürtzig 2019-03-21 Enh. #56: Export of Try elements implemented * Kay Gürtzig 2019-03-30 Issue #696: Type retrieval had to consider an alternative pool + * Kay Gürtzig 2019-11-19 Issues #423, #739: Support for struct and enum types (begun, continued 2019-12-01) + * Kay Gürtzig 2019-11-21 Enh. #423, #739: Enumerator stuff as well as record initializer handling revised + * Kay Gürtzig 2019-11-28 Issue #388: "use constant" approach withdrawn (except for enums), wrong lval references avoided * ****************************************************************************************************** * * Comment: LGPL license (http://www.gnu.org/licenses/lgpl.html). + * + * 2019-11-28 Issue #388 (KGU#375) + * - A temporary solution for constants (via use constant) had to be withdrawn because these constants cannot be scoped + * and don't behave like readonly variables, they can hardly be used with function calls or the like. * ******************************************************************************************************/// import java.util.HashMap; - +import java.util.Map.Entry; import java.util.regex.Matcher; +import java.util.regex.Pattern; import lu.fisch.structorizer.elements.Alternative; import lu.fisch.structorizer.elements.Call; @@ -104,6 +112,7 @@ import lu.fisch.structorizer.elements.Try; import lu.fisch.structorizer.elements.TypeMapEntry; import lu.fisch.structorizer.elements.While; +import lu.fisch.structorizer.executor.Function; import lu.fisch.structorizer.generators.Generator.TryCatchSupportLevel; import lu.fisch.structorizer.parsers.CodeParser; import lu.fisch.utils.StringList; @@ -211,6 +220,7 @@ protected String getIncludePattern() /************ Code Generation **************/ + private final Matcher varMatcher = Pattern.compile("^\\\\?[@$]?[$]?[A-Za-z_]\\w*$").matcher(""); // START KGU#311 2017-01-04: Enh. #314 File API analysis private StringList fileVars = new StringList(); // END KGU#311 2017-01-04 @@ -221,6 +231,11 @@ protected String getIncludePattern() private boolean isWithinCall = false; // END KGU#352 2017-02-26 + // START KGU#542 2019-11-20: Enh. #739 - Support enum types + /** Currently exported {@link Root} object. */ + private Root root; + // END KGU#542 2019-11-20 + // START KGU#18/KGU#23 2015-11-01 Transformation decomposed /** * A pattern how to embed the variable (right-hand side of an input instruction) @@ -277,41 +292,91 @@ protected String getOutputReplacer() @Override protected String transformTokens(StringList tokens) { + // START KGU#388/KGU#542 2019-11-19: Enh. #423, #739 transferred the stuff from transform(String) hitherto + // Manipulate a condensed token list copy simultaneously (makes it easier to locate neighbouring tokens) + StringList denseTokens = tokens.copy(); + denseTokens.removeAll(" "); // Condense + // Now transform all array and record initializers + // To go from right to left should ensure we advance from the innermost to the outermost brace + int posBraceL = tokens.lastIndexOf("{"); + int posBrace0L = denseTokens.lastIndexOf("{"); + while (posBraceL > 0) { + int posBrace0R = denseTokens.indexOf("}", posBrace0L + 1); + int posBraceR = tokens.indexOf("}", posBraceL + 1); + TypeMapEntry type = null; + if ((type = this.typeMap.get(denseTokens.get(posBrace0L-1))) != null && type.isRecord()) { + // Transform the condensed record initializer + StringList rInit = this.transformRecordInit(denseTokens.concatenate(null, posBrace0L-1, posBrace0R+1), type); + tokens.remove(posBraceL-1, posBraceR+1); + tokens.insert(rInit, posBraceL-1); + // Now do the analogous thing for the condensed token list + denseTokens.remove(posBrace0L-1, posBrace0R+1); + denseTokens.insert(rInit, posBrace0L-1);; + } + // The other case of '{' ... '}' (assumed to be a record initializer) can be ignored here, + // since it is sufficient to have the braces replaced by parentheses, which will be done below + posBraceL = tokens.lastIndexOf("{", posBraceL-1); + posBrace0L = denseTokens.lastIndexOf("{", posBrace0L + 1); + } + // END KGU#388/KGU#542 2019-11-19 // START KGU#62/KGU#103 2015-12-12: Bugfix #57 - We must work based on a lexical analysis + int posAsgn = tokens.indexOf("<-"); for (int i = 0; i < varNames.count(); i++) { String varName = varNames.get(i); + // Is it an enumeration constant? Then don't prefix it + String constVal = root.constants.get(varName); + if (constVal != null && constVal.startsWith(":") && constVal.contains("€")) { + //tokens.replaceAll(varName, constVal.substring(1, constVal.indexOf('€')) + '_' + varName); + continue; + } //System.out.println("Looking for " + varName + "..."); // FIXME (KGU): Remove after Test! //_input = _input.replaceAll("(.*?[^\\$])" + varName + "([\\W$].*?)", "$1" + "\\$" + varName + "$2"); // START KGU#352 2017-02-26: Different approaches for arrays and references //tokens.replaceAll(varName, "$"+varName); TypeMapEntry typeEntry = this.typeMap.get(varName); - if (typeEntry != null && typeEntry.isArray()) { - String prefix = ""; + if (typeEntry != null && (typeEntry.isArray() || typeEntry.isRecord())) { + String refPrefix = ""; + String prefix = typeEntry.isArray() ? "@" : "$"; int pos = -1; + int pos0 = -1; if (this.paramNames.contains(varName)) { - prefix = "$"; // dereference the variable + refPrefix = "$"; // dereference the variable } - while ((pos = tokens.indexOf(varName, pos+1)) >= 0) { + while ((pos = tokens.indexOf(varName)) >= 0) { // Array element access? - if (pos+3 < tokens.count() && tokens.get(pos+1).equals("[")) { - tokens.set(pos, "$" + prefix + varName); + pos0 = denseTokens.indexOf(varName, pos0+1); + if (pos0+3 < denseTokens.count() && denseTokens.get(pos0+1).equals("[")) { + tokens.set(pos, "$" + refPrefix + varName); } - else if (this.isWithinCall) { - // To pass an array to a subroutine we must use a reference - tokens.set(pos, "\\@" + prefix + varName); + else if (this.isWithinCall && pos > posAsgn) { + // To pass an array or record to a subroutine we must use a reference + // FIXME: for a component or the like the reference would have to be applied to all ("\($foo->bar)") + tokens.set(pos, "\\" + prefix + refPrefix + varName); } else { - tokens.set(pos, "@" + prefix + varName); + tokens.set(pos, prefix + refPrefix + varName); } } } else { - tokens.replaceAll(varName, "$"+varName); + // START KGU#388 2019-11-28: Enh. #423 - avoid to replace component names! + //tokens.replaceAll(varName, "$"+varName); + int pos = -1, pos0 = -1; + while ((pos = tokens.indexOf(varName, pos+1)) >= 0) { + pos0 = denseTokens.indexOf(varName, pos0+1); + if (pos0 == 0 || !denseTokens.get(pos0-1).equals(".")) { + tokens.set(pos, "$"+varName); + } + } + // END KGU#388 2019-11-28 } // END KGU#352 2017-02-26 } // END KGU#62/KGU#103 2015-12-12 + // START KGU#375 2019-11-28: Issue #388 - a "const" keyword must not remain here + tokens.removeAll("const"); + // END KGU#375 2019-11-28 // START KGU 2017-02-26 tokens.replaceAll("random", "rand"); // END KGU 2017-02-26 @@ -321,7 +386,32 @@ else if (this.isWithinCall) { tokens.replaceAll("{", "("); tokens.replaceAll("}", ")"); // END KGU#61 2016-03-23 - return tokens.concatenate(); + for (int i = 1; i < tokens.count()-1; i++) { + if (tokens.get(i).equals(".")) { + // Handle possible component access + int jL = i-1; + String pre = tokens.get(jL).trim(); + while (pre.isEmpty() && jL > 0) { + pre = tokens.get(--jL).trim(); + } + int jR = i+1; + String post = tokens.get(jR).trim(); + while (post.isEmpty() && jR < tokens.count()-1) { + post = tokens.get(++jR).trim(); + } + // START KGU#388 2019-11-29: Issue #423 - there are a lot of combinable prefixes + //if ((pre.equals("]") || Function.testIdentifier(pre, null) || pre.startsWith("$") && Function.testIdentifier(pre.substring(1), null)) + if ((pre.equals("]") || varMatcher.reset(pre).matches()) + // END KGU#388 2019-11-29 + && Function.testIdentifier(post, null)) { + tokens.remove(i+1, jR); + tokens.set(i, "->"); + tokens.remove(++jL, i); + i -= (i - jL); + } + } + } + return tokens.concatenate(null); } // END KGU#93 2015-12-21 @@ -340,17 +430,6 @@ protected String transform(String _input) { // END KGU#162 2016-04-01 _input = Element.unifyOperators(_input); - int asgnPos = _input.indexOf("<-"); // This might mutilate string literals! - if (asgnPos > 0) - { - String lval = _input.substring(0, asgnPos).trim(); - String expr = _input.substring(asgnPos + "<-".length()).trim(); - if (expr.startsWith("{") && expr.endsWith("}") && this.varNames.contains(lval)) - { - // The curly braces will be replaced with parentheses by transformTokens() - _input = "@" + lval + " <- " + expr; - } - } // START KGU#162 2016-04-01: Enh. #144 - hands off in "no conversion" mode } // END KGU#162 2016-04-01 @@ -406,17 +485,78 @@ protected void appendLabel(Element elem, String _indent) } // END KGU#78 2015-12-17 + // START KGU#388/KGU#542 2019-11-19: Enh. #423, #739 + private void generateTypeDef(Root _root, String _typeName, TypeMapEntry _type, String _indent, boolean _disabled) { + // TODO Auto-generated method stub + String indentPlus1 = _indent + this.getIndent(); + if (_type.isEnum()) { + // FIXME: This was a misconception, type name will not be needed + //addCode("use enum " + _typeName + "(" + _type.getEnumerationInfo().concatenate(" ") + ");", _indent, _disabled); + //addCode("use enum qw(:" + _typeName + "_ " + _type.getEnumerationInfo().concatenate(" ") + ");", _indent, _disabled); + addCode("use enum qw(" + _type.getEnumerationInfo().concatenate(" ") + ");", _indent, _disabled); + } + else if (_type.isRecord()) { + // FIXME Should we use Class::Struct or simply hashtables? Can the latter define a named type? + addCode("struct (" + _typeName + " => {", _indent, _disabled); + for (Entry compEntry: _type.getComponentInfo(true).entrySet()) { + String compTypeSymbol = "$"; + TypeMapEntry compType = compEntry.getValue(); + if (compType.isRecord()) { + compTypeSymbol = compType.typeName; + } + else if (compType.isArray()) { + compTypeSymbol = "@"; + } + // enum types are basically int, so '$' is okay + addCode(compEntry.getKey() + " => '" + compTypeSymbol + "',", indentPlus1, _disabled); + } + addCode(")};", _indent, _disabled); + } + } + // END KGU#388/KGU#542 2019-11-19 + + // START KGU#388 2019-11-19: Enh. #423 - support for record types + /** + * Transforms the record initializer into an adequate Perl code. + * @param _recordValue - the record initializer according to Structorizer syntax + * @param _typeEntry - used to interpret a simplified record initializer (may be null) + * @return a string representing an adequate Perl code for the initialisation. May contain + * indentation and newline characters + */ + protected StringList transformRecordInit(String _recordValue, TypeMapEntry _typeEntry) + { + StringList result = new StringList(); + result.add(_typeEntry.typeName + "->new(\n"); + HashMap comps = Instruction.splitRecordInitializer(_recordValue, _typeEntry, false); + for (Entry comp: comps.entrySet()) { + String compName = comp.getKey(); + String compVal = comp.getValue(); + if (!compName.startsWith("§") && compVal != null) { + result.add("\t" + compName); + result.add(" => "); + result.add(compVal); + result.add(",\n"); + } + } + result.add(");\n"); + return result; + } + // END KGU#388 2019-11-19 + + protected void generateCode(Instruction _inst, String _indent) { if (!appendAsComment(_inst, _indent)) { boolean isDisabled = _inst.isDisabled(); appendComment(_inst, _indent); + Root root = Element.getRoot(_inst); StringList lines = _inst.getUnbrokenText(); - for(int i=0;i 2) { @@ -434,8 +574,37 @@ protected void generateCode(Instruction _inst, String _indent) { continue; } // END KGU#653 219-02-15 + // START KGU#388/KGU#542 2019-11-19: Enh. #423, #739 + else if (Instruction.isTypeDefinition(line)) { + String typeName = line.substring(line.indexOf("type")+4, line.indexOf("=")).trim(); + TypeMapEntry type = this.typeMap.get(":" + typeName); + this.generateTypeDef(root, typeName, type, _indent, isDisabled); + continue; + } + else if (Instruction.isDeclaration(line) && !isAsgn) { + // Declarations will have been handled in the preamble + if (!_inst.getComment().trim().isEmpty()) { + appendComment(line, _indent); + } + continue; + } + // END KGU#388/KGU#542 2019-11-19 - String text = transform(line); + String text = null; + if (isAsgn) { + StringList tokens = Element.splitLexically(line, true); + tokens.removeAll(" "); + Element.unifyOperators(tokens, true); + int posAsgn = tokens.indexOf("<-"); + String var = Instruction.getAssignedVarname(tokens.subSequence(0, posAsgn), true); + StringList expr = tokens.subSequence(posAsgn+1, tokens.count()); + if (Function.testIdentifier(var, null) && expr.get(0).equals("{") && expr.get(expr.count()-1).equals("}")) { + text = "@" + var + " = " + transform(expr.concatenate(null)); + } + } + if (text == null) { + text = transform(line); + } if (!text.endsWith(";")) { text += ";"; } // START KGU#311 2017-01-04: Enh. #314 - steer the user through the File API implications if (this.usesFileAPI) { @@ -523,10 +692,10 @@ protected void generateCode(Instruction _inst, String _indent) { // START KGU#277/KGU#284 2016-10-13/16: Enh. #270 + Enh. #274 //code.add(_indent + text); - if (Instruction.isTurtleizerMove(_inst.getText().get(i))) { + if (Instruction.isTurtleizerMove(line)) { text += " " + this.commentSymbolLeft() + " color = " + _inst.getHexColor(); } - addCode(text, _indent, isDisabled); + addCode(text.replace("\t", this.getIndent()), _indent, isDisabled); // END KGU#277/KGU#284 2016-10-13 } } @@ -1023,6 +1192,9 @@ protected String generateHeader(Root _root, String _indent, String _procName, StringList _paramNames, StringList _paramTypes, String _resultType) { String indent = _indent; + // START KGU#542 2019-11-20: Enh. #739 - Support enum types + this.root = _root; + // END KGU#542 2019-11-20 // START KGU#352 2017-02-26: Cache transform-relevant information this.paramNames = _paramNames; // START KGU#676 2019-03-30: Enh. #696 special pool in case of batch export @@ -1046,6 +1218,9 @@ protected String generateHeader(Root _root, String _indent, String _procName, //if (_root.isProgram) { generatorIncludes.add("strict"); generatorIncludes.add("warnings"); + // START KGU#388 2019-11-19: Enh. #423 - Support for record types + generatorIncludes.add("Class::Struct"); + // END KGU#388 2019-11-19 //} // START KGU#348 2017-02-25: Enh. #348: Support for Parallel elements if (this.hasParallels) { @@ -1128,11 +1303,29 @@ protected String generatePreamble(Root _root, String _indent, StringList _varNam // code.add(_indent + "my $" + _varNames.get(v) + ";"); // FIXME (KGU) What about lists? // } //} + // START KGU#375/KGU#542 2019-11-19: Enh. #388, #739 - Support for constants (withdrawn for inconsistency) + //StringList paramNames = _root.getParameterNames(); + //for (Entry constEntry: _root.constants.entrySet()) { + // String constName = constEntry.getKey(); + // String constValue = constEntry.getValue(); + // // Skip arguments and enumeration items + // if (!paramNames.contains(constName) && !constValue.startsWith(":")) { + // addCode("use constant " + constName + " => " + transform(constValue) + ";", _indent, false); + // } + //} + // END KGU#375 2019-11-19 for (int v = 0; v < _varNames.count(); v++) { String varName = _varNames.get(v); TypeMapEntry typeEntry = this.typeMap.get(varName); - String prefix = (typeEntry != null && typeEntry.isArray()) ? "@" : "$"; - code.add(_indent + "my " + prefix + varName + ";"); + // START KGU#375/KGU#542 2019-12-01: Enh. #388, #739 - Don't declare enum constants here! + //String prefix = (typeEntry != null && typeEntry.isArray()) ? "@" : "$"; + //code.add(_indent + "my " + prefix + varName + ";"); + String constVal = _root.constants.get(varName); + if (constVal == null || !constVal.startsWith(":")) { + String prefix = (typeEntry != null && typeEntry.isArray()) ? "@" : "$"; + code.add(_indent + "my " + prefix + varName + ";"); + } + // END KGU#375/KGU#542 2019-11-19 } // END KGU#352 2017-02-26 code.add(_indent); diff --git a/src/lu/fisch/structorizer/generators/PythonGenerator.java b/src/lu/fisch/structorizer/generators/PythonGenerator.java index 984a38ba..1feb3328 100644 --- a/src/lu/fisch/structorizer/generators/PythonGenerator.java +++ b/src/lu/fisch/structorizer/generators/PythonGenerator.java @@ -74,6 +74,8 @@ * Kay Gürtzig 2019-03-30 Issue #696: Type retrieval had to consider an alternative pool * Kay Gürtzig 2019-05-28 Issue #725: Smarter export of division operator * Kay Gürtzig 2019-11-08 Bugfix #769: Undercomplex selector list splitting in CASE generation mended + * Kay Gürtzig 2019-11-24 Bugfix #782: Declaration of global variables corrected + * Kay Gürtzig 2019-12-01 Enh. #739: Support for enumerator types * ****************************************************************************************************** * @@ -114,7 +116,6 @@ ******************************************************************************************************/// import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map.Entry; @@ -242,6 +243,10 @@ protected String getIncludePattern() /************ Code Generation **************/ + // START KGU#542 2019-12-01: Enh. #739 - support for enumerator types + /** The currently exported {@link Root} */ + private Root root = null; + // END KGU#542 2019-12-01 // START KGU#388 2017-10-02: Enh. #423 - Support for recordtypes /** cache for the type map of the current Root */ private HashMap typeMap = null; @@ -335,6 +340,7 @@ protected String transformTokens(StringList tokens) int j = i; // Skip all whitespace while (j+2 < tokens.count() && tokens.get(++j).trim().isEmpty()); + // Handle DiagramController (more specifically: Turtleizer) routine calls // START KGU#480 2018-01-21: Enh. 490 - more precise detection //String turtleMethod = null; //if (j+1 < tokens.count() && tokens.get(j).equals("(") && (turtleMethod = Turtleizer.checkRoutine(token)) != null) { @@ -360,6 +366,14 @@ protected String transformTokens(StringList tokens) } } // END KGU#480 2018-01-21 + // START KGU#542 2019-12-01: Enh. #739 support for enumerators + else if (this.varNames.contains(token) && this.root != null && this.root.constants.get(token) != null) { + String constVal = this.root.constants.get(token); + if (constVal.startsWith(":") && constVal.contains("€")) { + tokens.set(i, constVal.substring(1, constVal.indexOf("€"))+ "." + token); + } + } + // END KGU#542 2019-12-01 } } // START KGU 2014-11-16: C comparison operator required conversion before logical ones @@ -389,9 +403,9 @@ protected String transformTokens(StringList tokens) // START KGU#388 2017-10-02: Enh. #423 Record support /** - * Recursively looks for record initializers in the tokens and if there are some replaces + * Recursively looks for record initializers in the tokens and, if there are some, replaces * the respective type name token by the entire transformed record initializer as single - * string element and hence immune against further token manipulations. + * string element (which is hence immune against further token manipulations).
* @param tokens - the token list of the split line, will be modified. */ private void transformRecordInitializers(StringList tokens) { @@ -409,7 +423,7 @@ private void transformRecordInitializers(StringList tokens) { // We will now reorder the elements and drop the names // START KGU#559 2018-07-20: Enh. #563 - smarter record initialization //HashMap comps = Instruction.splitRecordInitializer(tokens.concatenate("", posLBrace)); - HashMap comps = Instruction.splitRecordInitializer(tokens.concatenate("", posLBrace), typeEntry); + HashMap comps = Instruction.splitRecordInitializer(tokens.concatenate("", posLBrace), typeEntry, false); // END KGU#559 2018-07-20 LinkedHashMap compDefs = typeEntry.getComponentInfo(true); String tail = comps.get("§TAIL§"); // String part beyond the initializer @@ -572,6 +586,7 @@ protected void generateCode(Instruction _inst, String _indent) // END KGU 2014-11-16 StringList lines = _inst.getUnbrokenText(); String tmpCol = null; + Root root = Element.getRoot(_inst); for(int i = 0; i < lines.count(); i++) { // START KGU#277/KGU#284 2016-10-13/16: Enh. #270 + Enh. #274 @@ -612,9 +627,14 @@ else if (Instruction.isTurtleizerMove(line)) { else if (Instruction.isTypeDefinition(line)) { mtchTypename.reset(line).matches(); String typeName = mtchTypename.group(1); - done = this.generateTypeDef(Element.getRoot(_inst), typeName, null, _indent, isDisabled); + done = this.generateTypeDef(root, typeName, null, _indent, isDisabled); } // END KGU#388 2017-10-02 + // START KGU#767 2019-11-24: Bugfix #782 We must handle variable declarations as unspecified oinitialisations + else if (Instruction.isMereDeclaration(line)) { + done = generateDeclaration(line, root, _indent, isDisabled); + } + // END KGU#767 2019-11-24 if (!done) { addCode(codeLine, _indent, isDisabled); } @@ -1064,7 +1084,7 @@ protected void generateCode(Try _try, String _indent) // START KGU#388 2017-10-02: Enh. #423 Translate record types to mutable recordtypes /** - * Adds a typedef or struct definition for the type passed in by {@code _typeEnry} + * Adds a typedef, struct, or enum definition for the type passed in by {@code _typeEnry} * if it hadn't been defined globally or in the preamble before. * @param _root - the originating Root * @param _type - the type map entry the definition for which is requested here @@ -1096,6 +1116,32 @@ else if (_type == null) { addCode(typeDef, _indent, _asComment); done = true; } + // START KGU#542 2019-12-01: Enh. #739 - Support for enumeration types (since Python 3.4) + else if (_type.isEnum()) { + String indentPlus1 = _indent + this.getIndent(); + StringList enumItems = _type.getEnumerationInfo(); + addCode("class " + _typeName + "(Enum):", _indent, _asComment); + int offset = 0; + String lastVal = ""; + for (int i = 0; i < enumItems.count(); i++) { + String[] itemSpec = enumItems.get(i).split("=", 2); + if (itemSpec.length > 1) { + lastVal = itemSpec[1].trim(); + offset = 0; + try { + int code = Integer.parseUnsignedInt(lastVal); + lastVal = ""; + offset = code; + } + catch (NumberFormatException ex) {} + } + addCode(itemSpec[0] + " = " + transform(lastVal) + (lastVal.isEmpty() ? "" : "+") + offset, indentPlus1, _asComment); + offset++; + } + addCode("", _indent, _asComment); + done = true; + } + // END KGU#542 2019-12-01 return done; } @@ -1125,41 +1171,84 @@ protected void appendGlobalInitialisations(String _indent) { * @param _root - the Root being exported * @param _indent - the current indentation level * @see #appendGlobalInitialisations(String) + * @see #generateDeclaration(String, Root, String, boolean) */ private void appendGlobalDeclarations(Root _root, String _indent) { - if (_root.includeList != null) { - HashSet declared = new HashSet(); - for (Root incl: this.includedRoots) { - if (_root.includeList.contains(incl.getMethodName())) { - // Start with the types - // START KGU#676 2019-03-30: Enh. #696 special pool in case of batch export - //for (String name: incl.getTypeInfo().keySet()) { - for (String name: incl.getTypeInfo(routinePool).keySet()) { - // END KGU#676 2019-03-30 - if (name.startsWith(":") && !declared.contains((name = name.substring(1)))) { - addCode("global " + name, _indent, false); - declared.add(name); - } - } - // Now add the variables (including constants) - StringList names = incl.retrieveVarNames(); - for (int i = 0; i < names.count(); i++) - { - String name = names.get(i); - if (!declared.contains(name)) { - addCode("global " + name, _indent, false); - declared.add(name); - } - } + // START KGU#767 2019-11-24: Bugfix #782 Fundamentally revised +// if (_root.includeList != null) { +// HashSet declared = new HashSet(); +// for (Root incl: this.includedRoots) { +// if (_root.includeList.contains(incl.getMethodName())) { +// // Start with the types +// // START KGU#676 2019-03-30: Enh. #696 special pool in case of batch export +// //for (String name: incl.getTypeInfo().keySet()) { +// for (String name: incl.getTypeInfo(routinePool).keySet()) { +// // END KGU#676 2019-03-30 +// if (name.startsWith(":") && !declared.contains((name = name.substring(1)))) { +// addCode("global " + name, _indent, false); +// declared.add(name); +// } +// } +// // Now add the variables (including constants) +// StringList names = incl.retrieveVarNames(); +// for (int i = 0; i < names.count(); i++) +// { +// String name = names.get(i); +// if (!declared.contains(name)) { +// addCode("global " + name, _indent, false); +// declared.add(name); +// } +// } +// } +// } +// if (!declared.isEmpty()) { +// addCode("", _indent, false); +// } +// } + for (String name: this.typeMap.keySet()) { + if (this.wasDefHandled(_root, name, false, true) && !this.wasDefHandled(_root, name, true, false)) { + if (name.startsWith(":")) { + name = name.substring(1); } - } - if (!declared.isEmpty()) { - addCode("", _indent, false); + addCode("global " + name, _indent, false); } } + // END KGU#767 2019-11-24 } // END KGU#388 2017-10-02 + // START KGU#767 2019-11-24: Bugfix #782 - wrong handling of global / local declarations + /** + * Generates a declaration from the given line and registers it with the given root. + * @param _line - the original line of the declaration + * @param _root - the owning {@link Root} object + * @param _indent - current indentation level + * @param _isDisabled - whether this element is disabled (i.e. all content is going to be a comment) + * @return true iff all code generation for the instruction line is done + */ + private boolean generateDeclaration(String _line, Root _root, String _indent, boolean _isDisabled) { + StringList tokens = Element.splitLexically(_line + " <- 0", true); + tokens.removeAll(" "); + String varName = Instruction.getAssignedVarname(tokens, false); + if (this.wasDefHandled(_root, varName, false)) { + return true; + } + String typeComment = ""; + TypeMapEntry type = this.typeMap.get(varName); + if (type != null) { + StringList typeNames = this.getTransformedTypes(type, true); + if (typeNames != null && !typeNames.isEmpty()) { + typeComment = "\t" + this.commentSymbolLeft() + + " meant to be of type " + typeNames.concatenate(" or ") + " " + + this.commentSymbolRight(); + } + } + addCode(varName + " = None" + typeComment, _indent, _isDisabled); + this.setDefHandled(_root.getSignatureString(false), varName); + return true; + } + // END KGU#767 2019-11-24 + /* (non-Javadoc) * @see lu.fisch.structorizer.generators.Generator#generateHeader(lu.fisch.structorizer.elements.Root, java.lang.String, java.lang.String, lu.fisch.utils.StringList, lu.fisch.utils.StringList, java.lang.String) */ @@ -1179,13 +1268,20 @@ protected String generateHeader(Root _root, String _indent, String _procName, // START KGU#363 2017-05-16: Enh. #372 appendCopyright(_root, _indent, true); // END KGU#363 2017-05-16 + appendComment("You should have installed module recordtype: pip install recordtype", _indent); + appendComment(this.getIndent() + "See https://pypi.org/project/recordtype", _indent); + code.add(_indent + "from recordtype import recordtype"); + // START KGU#542 2019-12-01: Enh. #739 + code.add(_indent + "from enum import Enum"); + this.generatorIncludes.add("enum"); + // END KGU#542 2019-12-01 // START KGU#348 2017-02-19: Enh. #348 - Translation of parallel sections if (this.hasParallels) { code.add(_indent); code.add(_indent + "from threading import Thread"); } // END KGU#348 2017-02-19 - // START KGU#607 2018-10-30:Issue #346 + // START KGU#607 2018-10-30: Issue #346 this.generatorIncludes.add("math"); // Will be inserted later // END KGU#607 2018-10-30 // START KGU#351 2017-02-26: Enh. #346 @@ -1238,6 +1334,9 @@ protected String generateHeader(Root _root, String _indent, String _procName, this.typeMap = _root.getTypeInfo(routinePool); // END KGU#676 2019-03-30 // END KGU#388 2017-10-02 + // START KGU#542 2019-12-01: Enh. #739 - For enumerator transformation, we will also need _root in in deeper contexts + this.root = _root; + // END KGU#542 2019-12-01 return indent; } @@ -1248,7 +1347,9 @@ protected String generateHeader(Root _root, String _indent, String _procName, protected String generatePreamble(Root _root, String _indent, StringList _varNames) { // START KGU#376 2017-10-03: Enh. #389 - Variables and types of the included diagrams must be marked as global here + // START KGU#767 2019-11-24: Bugfix #782: Disabled, will now be done via generateDeclaration() from generateCode(Instruction...) appendGlobalDeclarations(_root, _indent); + // END KGU#767 2019-11-24 // END KGU#376 2017-10-03 // START KGU#348 2017-02-19: Enh. #348 - Translation of parallel sections generateParallelThreadFunctions(_root, _indent); diff --git a/src/lu/fisch/structorizer/generators/SubTopoSortEntry.java b/src/lu/fisch/structorizer/generators/SubTopoSortEntry.java index 015c78bd..cf3b7ed8 100644 --- a/src/lu/fisch/structorizer/generators/SubTopoSortEntry.java +++ b/src/lu/fisch/structorizer/generators/SubTopoSortEntry.java @@ -34,6 +34,7 @@ * ------ ---- ----------- * Kay Gürtzig 2016.07.19 First issue (for enh. #160) * Kay Gürtzig 2016.08.10 Modification for bugfix #228 (KGU#237) +* Kay Gürtzig 2019-12-03 Issue #766: Sorted caller set to achieve deterministic routine order * ****************************************************************************************************** * @@ -41,8 +42,7 @@ * ******************************************************************************************************/// -import java.util.HashSet; -import java.util.Set; +import java.util.TreeSet; import lu.fisch.structorizer.elements.Root; @@ -52,7 +52,10 @@ * depends on). */ final class SubTopoSortEntry { - public Set callers = new HashSet(); + // START KGU#754 2019-12-03: Issue #766 - we want deterministic routine orders + //public Set callers = new HashSet(); + public TreeSet callers = new TreeSet(Root.SIGNATURE_ORDER); + // END KGU#754 2019-12-03 public int nReferingTo = 0; // number of different(!) routines being called SubTopoSortEntry(Root _caller) diff --git a/src/lu/fisch/structorizer/generators/TexGenerator.java b/src/lu/fisch/structorizer/generators/TexGenerator.java index d11085f4..0c23269d 100644 --- a/src/lu/fisch/structorizer/generators/TexGenerator.java +++ b/src/lu/fisch/structorizer/generators/TexGenerator.java @@ -301,7 +301,7 @@ else if (!Instruction.isAssignment(line) && Instruction.isDeclaration(line)) { // get the variable name StringList tokens = Element.splitLexically(line + "<-", true); tokens.removeAll(" "); - String varName = Instruction.getAssignedVarname(tokens); + String varName = Instruction.getAssignedVarname(tokens, false); code.add(_indent+this.getIndent()+this.getIndent() + "\\description{" + varName + "}{" + transform(line) + "}"); code.add(_indent+this.getIndent() + "\\end{declaration}"); diff --git a/src/lu/fisch/structorizer/generators/XmlGenerator.java b/src/lu/fisch/structorizer/generators/XmlGenerator.java index fe68c164..27890683 100644 --- a/src/lu/fisch/structorizer/generators/XmlGenerator.java +++ b/src/lu/fisch/structorizer/generators/XmlGenerator.java @@ -49,8 +49,9 @@ * Kay Gürtzig 2017.03.13 Enh. #372: License attributes/elements added (Simon Sobisch) * Kay Gürtzig 2017.03.28 Enh. #370: Alternative keyword set may be saved (un-refactored diagrams) * Kay Gürtzig 2017.05.22 Enh. #372: New attribute "origin" added. - * Kay Gürtuig 2017.06.30 Enh. #389: New attribute "includeList" added. + * Kay Gürtzig 2017.06.30 Enh. #389: New attribute "includeList" added. * Kay Gürtzig 2019-03-17 Enh. #56: Method generateCode(Try, String) implemented. + * Kay Gürtzig 2019-11-13 Method loadLicenseText moved to Generator in order to fix bug #778 * ****************************************************************************************************** * @@ -517,48 +518,49 @@ public String generateCode(Root _root, String _indent) return code.getText(); } - private String loadLicenseText(String licName) { - String error = null; - String content = ""; - File licDir = Ini.getIniDirectory(); - String licFileName = LicFilter.getNamePrefix() + licName + "." + LicFilter.acceptedExtension(); - File[] licFiles = licDir.listFiles(new LicFilter()); - File licFile = null; - for (int i = 0; licFile == null && i < licFiles.length; i++) { - if (licFileName.equalsIgnoreCase(licFiles[i].getName())) { - licFile = licFiles[i]; - } - } - BufferedReader br = null; - try { - InputStreamReader isr = new InputStreamReader(new FileInputStream(licFile), "UTF-8"); - br = new BufferedReader(isr); - String line = null; - while ((line = br.readLine()) != null) { - content += line + '\n'; - }; - } catch (UnsupportedEncodingException e) { - error = e.getMessage(); - } catch (FileNotFoundException e) { - error = e.getMessage(); - } catch (IOException e) { - error = e.getMessage(); - } - if (br != null) { - try { - br.close(); - } catch (IOException e) { - error = e.getMessage(); - } - } - if (error != null) { - getLogger().log(Level.WARNING, "{0}", error); - } - if (content.trim().isEmpty()) { - content = null; - } - return content; - } +// START KGU#763 2019-11-13: Bugfix #778 - moved to class Generator +// private String loadLicenseText(String licName) { +// String error = null; +// String content = ""; +// File licDir = Ini.getIniDirectory(); +// String licFileName = LicFilter.getNamePrefix() + licName + "." + LicFilter.acceptedExtension(); +// File[] licFiles = licDir.listFiles(new LicFilter()); +// File licFile = null; +// for (int i = 0; licFile == null && i < licFiles.length; i++) { +// if (licFileName.equalsIgnoreCase(licFiles[i].getName())) { +// licFile = licFiles[i]; +// } +// } +// BufferedReader br = null; +// try { +// InputStreamReader isr = new InputStreamReader(new FileInputStream(licFile), "UTF-8"); +// br = new BufferedReader(isr); +// String line = null; +// while ((line = br.readLine()) != null) { +// content += line + '\n'; +// }; +// } catch (UnsupportedEncodingException e) { +// error = e.getMessage(); +// } catch (FileNotFoundException e) { +// error = e.getMessage(); +// } catch (IOException e) { +// error = e.getMessage(); +// } +// if (br != null) { +// try { +// br.close(); +// } catch (IOException e) { +// error = e.getMessage(); +// } +// } +// if (error != null) { +// getLogger().log(Level.WARNING, "{0}", error); +// } +// if (content.trim().isEmpty()) { +// content = null; +// } +// return content; +// } // @Override - obsolete since 3.27 // public String[] getReservedWords() { @@ -571,6 +573,6 @@ private String loadLicenseText(String licName) { // // Auto-generated method stub // return false; // } - +// END KGU#763 2019-11-13 } diff --git a/src/lu/fisch/structorizer/gui/Diagram.java b/src/lu/fisch/structorizer/gui/Diagram.java index 8ff0aa4f..946d7749 100644 --- a/src/lu/fisch/structorizer/gui/Diagram.java +++ b/src/lu/fisch/structorizer/gui/Diagram.java @@ -190,6 +190,8 @@ * Kay Gürtzig 2019-10-05 Issues #758 (Edit subroutine) and KGU#743 (root type change) fixed * Kay Gürtzig 2019-10-07 Error message fallback for cases of empty exception text ensured (KGU#747) * Kay Gürtzig 2019-10-13/15 Bugfix #763: Stale file also triggers save request in saveNSD() + * Bob Fisch 2019-11-24 New method setRootForce() introduced as interface for Unimozer (c) + * Kay Gürtzig 2019-11-29 Bugfix #777: Concurrent favourite export language modification now properly handled * ****************************************************************************************************** * @@ -571,36 +573,50 @@ public boolean setRootIfNotRunning(Root root) { this.getParent().getParent().requestFocusInWindow(); // It's the JScrollPane (Editor.scrollaraea) return setRoot(root, true, true); } - - - public boolean setRootForce(Root root) + + // START BOB 2019-11-24: Unimozer needs this method + /** + * Replaces the current {@link Root} by the given {@code root} (if not null) + * and updates all depending GUI elements.
+ * CAUTION: Special interface for embedded use in Unimozer. Does not protect + * unsaved changes to the recently held {@link Root}! + * @param root - The new {@link Root} object (NSD) to be shown. + * @return true (no matter what happened) + * @see #setRoot(Root, boolean, boolean) + * @see #setRootIfNotRunning(Root) + */ + public boolean setRootForce(Root root) { - if (root != null) - { - this.root = root; - selected = root.findSelected(); - if (selected == null) - { - selected = root; - root.setSelected(true); - } - redraw(); - analyse(); - this.updateCodePreview(); - doButtons(); - adaptScrollUnits(); - } - return true; - } + if (root != null) + { + this.root = root; + selected = root.findSelected(); + if (selected == null) + { + selected = root; + root.setSelected(true); + } + redraw(); + analyse(); + this.updateCodePreview(); + doButtons(); + adaptScrollUnits(); + } + return true; + } + // END BOB 2019-11-24 // START KGU#430 2017-10-12: Issue #432 allow to set the root without immediate redrawing /** * Replaces the current {@link Root} by the given {@code root} and updates all - * depending GUI elements. + * depending GUI elements.
+ * Should not be used while Executor is running the current Root - consider using {@link #setRootIfNotRunning(Root)} + * instead, which does a preliminary check. * @param root - the new diagram root * @param askToSave - in case the rcent {@link Root} has unsaved changes, ask to save it? * @param draw - If true then the work area will be redrawn - * @return true if {@code root} wasn't null ad has properly replaced the current diagram + * @return true if {@code root} wasn't null and has properly replaced the current diagram + * @see #setRootIfNotRunning(Root) */ //public boolean setRoot(Root root, boolean askToSave) public boolean setRoot(Root root, boolean askToSave, boolean draw) @@ -611,7 +627,7 @@ public boolean setRoot(Root root, boolean askToSave, boolean draw) // Save if something has been changed if (!saveNSD(askToSave)) { - // Abort this if the user cancels the save request + // Abort this if the user cancels the save request return false; } this.unselectAll(draw); @@ -644,7 +660,7 @@ public boolean setRoot(Root root, boolean askToSave, boolean draw) adaptScrollUnits(); // END KGU#44 2017-10-23 } - return true; + return root != null; } // END KGU#48,KGU#49 2015-10-18 @@ -2037,7 +2053,7 @@ public void openNSD() dlgOpen.setFileFilter(filter); // END KGU 2016-01-15 // show & get result - int result = dlgOpen.showOpenDialog(this.NSDControl.getFrame()); + int result = dlgOpen.showOpenDialog(this.getFrame()); // react on result if (result == JFileChooser.APPROVE_OPTION) { @@ -2171,7 +2187,7 @@ public void openNSD(String _filename) // START KGU#111 2015-12-16: Bugfix #63: No error messages on failed load if (errorMessage != null) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), "\"" + _filename + "\": " + errorMessage, + JOptionPane.showMessageDialog(this.getFrame(), "\"" + _filename + "\": " + errorMessage, Menu.msgTitleLoadingError.getText(), JOptionPane.ERROR_MESSAGE); } @@ -2214,7 +2230,7 @@ private boolean handleKeywordDifferences(boolean isChangeRequest) { for (int i = 0; i < optionTexts.length; i++) { menuText += (char)('a' + i) + ") " + optionTexts[i] + (i+1 < optionTexts.length ? "," : ".") + "\n"; } - int answer = JOptionPane.showOptionDialog(this.NSDControl.getFrame(), + int answer = JOptionPane.showOptionDialog(this.getFrame(), Menu.msgKeywordsDiffer.getText().replace("%1", "\n" + replacements.getText() + "\n").replace("%2", menuText), Menu.msgTitleQuestion.getText(), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, @@ -2287,11 +2303,11 @@ private void loadArrangement(File arrFile) errorMsg = Menu.msgErrorNoFile.getText(); } else { - errorMsg = arr.loadArrangement((Mainform)NSDControl.getFrame(), arrFile); + errorMsg = arr.loadArrangement((Mainform)this.getFrame(), arrFile); } // END KGU#671 2019-03-01 if (!errorMsg.isEmpty()) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), "\"" + arrFile + "\": " + errorMsg, + JOptionPane.showMessageDialog(this.getFrame(), "\"" + arrFile + "\": " + errorMsg, Menu.msgTitleLoadingError.getText(), JOptionPane.ERROR_MESSAGE); } @@ -2318,12 +2334,12 @@ public void saveAllNSD() startSerialMode(); try { if ((saveNSD(false) - || JOptionPane.showConfirmDialog(this.NSDControl.getFrame(), + || JOptionPane.showConfirmDialog(this.getFrame(), Menu.msgCancelAll.getText(), Menu.msgTitleSave.getText(), JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) && Arranger.hasInstance()) { - Arranger.getInstance().saveAll(this.NSDControl.getFrame()); + Arranger.getInstance().saveAll(this.getFrame()); } } finally { @@ -2415,7 +2431,7 @@ else if (answer == 2) { //int result = dlgSave.showSaveDialog(this); int result = JFileChooser.ERROR_OPTION; do { - result = dlgSave.showSaveDialog(this.NSDControl.getFrame()); + result = dlgSave.showSaveDialog(this.getFrame()); // END KGU#248 2016-9-15 if (result == JFileChooser.APPROVE_OPTION) { @@ -2538,7 +2554,7 @@ private int checkOverwrite(File f, boolean showFilename) { message = Menu.msgOverwriteFile1.getText().replaceAll("%", f.getAbsolutePath()); } int res = JOptionPane.showOptionDialog( - this.NSDControl.getFrame(), + this.getFrame(), message, Menu.btnConfirmOverwrite.getText(), JOptionPane.DEFAULT_OPTION, @@ -2567,7 +2583,7 @@ else if (res == 2) { else { // END KGU#534 2018-06-27 int res = JOptionPane.showConfirmDialog( - this.NSDControl.getFrame(), + this.getFrame(), Menu.msgOverwriteFile.getText(), Menu.btnConfirmOverwrite.getText(), JOptionPane.YES_NO_OPTION); @@ -2644,8 +2660,10 @@ public boolean saveNSD(Root root, boolean _askToSave) } message = Menu.msgSaveChanges.getText() + "\n\"" + filename + "\""; } - if(this.NSDControl==null) return false; - res = requestSaveDecision(message, this.NSDControl.getFrame(), SerialDecisionAspect.SERIAL_SAVE); + // START BOB 2019-10-16: Unimozer crashed with a NullPointerException + if (this.NSDControl==null) return false; + // END BOB 2019-10-16 + res = requestSaveDecision(message, this.getFrame(), SerialDecisionAspect.SERIAL_SAVE); // START KGU#534 2018-06-27: Enh. #552 //if (res==0) @@ -2705,7 +2723,7 @@ public boolean saveNSD(Root root, boolean _askToSave) //res = -1; // Cancel all if (!Element.E_AUTO_SAVE_ON_CLOSE || !isGoingToClose - || JOptionPane.showConfirmDialog(this.NSDControl.getFrame(), + || JOptionPane.showConfirmDialog(this.getFrame(), Menu.msgVetoClose.getText(), Menu.msgTitleWarning.getText(), JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) { @@ -2888,7 +2906,7 @@ else if (fileExisted) new Object[]{filename, f.getAbsolutePath()}); String errors = Archivar.copyFile(tmpFile, f, true); if (!errors.isEmpty()) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgErrorFileRename.getText().replace("%1", errors).replace("%2", tmpFile.getAbsolutePath()), Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE, null); @@ -2918,7 +2936,7 @@ else if (fileExisted) String message = ex.getLocalizedMessage(); if (message == null) message = ex.getMessage(); if (message == null || message.isEmpty()) message = ex.toString(); - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgErrorFileSave.getText().replace("%", message), Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE, null); @@ -3003,7 +3021,7 @@ private boolean zipToArrz(Root root, String tmpFilename) } } if (error != null) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), error, Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE, null); @@ -4095,7 +4113,7 @@ public void outsourceNSD() try { redraw(); String[] options = new String[]{Menu.lblContinue.getText(), Menu.lblCancel.getText()}; - answer = JOptionPane.showOptionDialog(this.NSDControl.getFrame(), + answer = JOptionPane.showOptionDialog(this.getFrame(), Menu.msgJumpsOutwardsScope.getText().replace("%", jumpTexts), Menu.msgTitleWarning.getText(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, @@ -4144,11 +4162,11 @@ public void outsourceNSD() // If the diagram is a program then create an exclusive group named after the main diagram if (root.isProgram()) { targetGroupName = root.getMethodName(true); - Arranger.getInstance().addToPool(root, this.NSDControl.getFrame(), targetGroupName); + Arranger.getInstance().addToPool(root, this.getFrame(), targetGroupName); groups = Arranger.getInstance().getGroupsFromRoot(root, true); } else { - Arranger.getInstance().addToPool(root, this.NSDControl.getFrame()); + Arranger.getInstance().addToPool(root, this.getFrame()); } } else if (Arranger.getInstance().getGroupsFromRoot(root, false).size() == groups.size()) { @@ -4177,7 +4195,7 @@ else if (Arranger.getInstance().getGroupsFromRoot(root, false).size() == groups. // Associate the subroutine to all groups root is member of if (groups != null) { for (Group group: groups) { - Arranger.getInstance().attachRootToGroup(group, sub, null, this.NSDControl.getFrame()); + Arranger.getInstance().attachRootToGroup(group, sub, null, this.getFrame()); } } // END KGU#626 2019-01-06 @@ -4286,7 +4304,7 @@ else if (typeSource != null) { // Associate the includable to all groups root is member of if (groups != null) { for (Group group: groups) { - Arranger.getInstance().attachRootToGroup(group, incl, null, this.NSDControl.getFrame()); + Arranger.getInstance().attachRootToGroup(group, incl, null, this.getFrame()); } } // END KGU#626 2019-01-06 @@ -4429,7 +4447,7 @@ else if (candidates.size() > 1) { if (((Call)selected).isFunctionCall()) { StringList lineTokens = Element.splitLexically(call.getUnbrokenText().get(0), true); lineTokens.removeAll(" "); - String var = Call.getAssignedVarname(lineTokens); + String var = Call.getAssignedVarname(lineTokens, true); if (Function.testIdentifier(var, null)) { TypeMapEntry typeEntry = root.getTypeInfo().get(var); result = typeEntry.getCanonicalType(true, true).replace("@", "array of "); @@ -4452,11 +4470,11 @@ else if (candidates.size() > 1) { // If the diagram is a program then create an exclusive group named after the main diagram if (root.isProgram()) { targetGroupName = root.getMethodName(true); - Arranger.getInstance().addToPool(root, this.NSDControl.getFrame(), targetGroupName); + Arranger.getInstance().addToPool(root, this.getFrame(), targetGroupName); myGroups = Arranger.getInstance().getGroupsFromRoot(root, true); } else { - Arranger.getInstance().addToPool(root, this.NSDControl.getFrame()); + Arranger.getInstance().addToPool(root, this.getFrame()); } } else if (Arranger.getInstance().getGroupsFromRoot(root, false).size() == myGroups.size()) { @@ -5032,7 +5050,7 @@ public int getNumberOfReplacements() switcher.activate(); selected.traverse(switcher); } - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgReplacementsDone.getText().replace("%", Integer.toString(nReplaced))); // END #272 2016-10-17 // START KGU#705 2019-09-23: Enh. #738 @@ -5122,7 +5140,7 @@ public void stateChanged(ChangeEvent e) { cbRecursive.addChangeListener(changeListener); int answer = JOptionPane.showConfirmDialog( - this.NSDControl.getFrame(), pnl, + this.getFrame(), pnl, Menu.ttlBreakTextLines.getText(), JOptionPane.OK_CANCEL_OPTION); @@ -5198,7 +5216,7 @@ public void editBreakTrigger() { { int trigger = ele.getBreakTriggerCount(); // FIXME: Replace this quick-and-dirty approach by something more functional - String str = JOptionPane.showInputDialog(this.NSDControl.getFrame(), + String str = JOptionPane.showInputDialog(this.getFrame(), Menu.msgBreakTriggerPrompt.getText(), Integer.toString(trigger)); if (str != null) @@ -5230,7 +5248,7 @@ public void editBreakTrigger() { } // START KGU#252 2016-09-21: Issue 248 - Linux (Java 1.7) workaround if (!isDone) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgBreakTriggerIgnored.getText(), Menu.msgTitleWrongInput.getText(), JOptionPane.ERROR_MESSAGE); @@ -5452,7 +5470,7 @@ else if(root.getFile()!=null) if(file.exists()) { - int response = JOptionPane.showConfirmDialog (this.NSDControl.getFrame(), + int response = JOptionPane.showConfirmDialog (this.getFrame(), Menu.msgOverwriteFiles.getText(), Menu.btnConfirmOverwrite.getText(), JOptionPane.YES_NO_OPTION, @@ -5542,7 +5560,7 @@ else if(root.getFile()!=null) } catch(Exception e) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgErrorImageSave.getText(), Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE); @@ -5642,7 +5660,7 @@ else if(root.getFile()!=null) } catch(Exception e) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgErrorImageSave.getText(), Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE); @@ -6153,7 +6171,7 @@ public void importNSD(String _className, Vector> _specif String message = ex.getLocalizedMessage(); if (message == null) message = ex.getMessage(); if (message == null || message.isEmpty()) message = ex.toString(); - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), message, + JOptionPane.showMessageDialog(this.getFrame(), message, Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE); // START KGU#484 2018-04-05: Issue #463 //ex.printStackTrace(); @@ -6361,7 +6379,7 @@ public void importCode(/*String _parserClassName,*/) File file = dlgOpen.getSelectedFile().getAbsoluteFile(); if (!file.canRead()) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgImportFileReadError.getText().replace("%", file.getPath())); return; } @@ -6372,7 +6390,7 @@ public void importCode(/*String _parserClassName,*/) parser = identifyParser(file, filter); if (parser == null) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgImportCancelled.getText().replace("%", file.getPath())); return; } @@ -6432,7 +6450,7 @@ else if (logPath.equals(".")) { // ); ImportWorker worker = new ImportWorker(parser, file, ini,logPath); // Pop up the progress monitor (it will be closed via the OK buttons). - new CodeImportMonitor(this.NSDControl.getFrame(), worker, parser.getDialogTitle()); + new CodeImportMonitor(this.getFrame(), worker, parser.getDialogTitle()); List newRoots = worker.get(); // END KGU#537 2018-06-30 // END KGU#265 2016-09-28 @@ -6452,7 +6470,7 @@ else if (logPath.equals(".")) { int maxRoots = Integer.parseInt(ini.getProperty("impMaxRootsForDisplay", "20")); if (nRoots > maxRoots) { String[] options = {Menu.lblContinue.getText(), Menu.lblCancel.getText()}; - int chosen = JOptionPane.showOptionDialog(this.NSDControl.getFrame(), + int chosen = JOptionPane.showOptionDialog(this.getFrame(), Menu.msgTooManyDiagrams.getText().replace("%", Integer.toString(maxRoots)), Menu.ttlCodeImport.getText(), JOptionPane.YES_NO_OPTION, @@ -6471,7 +6489,7 @@ else if (logPath.equals(".")) { // If the saving attempt fails, ask whether the saving loop is to be cancelled if (!this.saveNSD(nextRoot, false)) { if (JOptionPane.showConfirmDialog( - this.NSDControl.getFrame(), + this.getFrame(), Menu.msgCancelAll.getText(), Menu.ttlCodeImport.getText(), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { @@ -6547,7 +6565,7 @@ else if (logPath.equals(".")) { // Menu.msgTitleParserError.getText(), // JOptionPane.ERROR_MESSAGE, null); String[] options = {Menu.lblOk.getText(), Menu.lblCopyToClipBoard.getText()}; - int chosen = JOptionPane.showOptionDialog(this.NSDControl.getFrame(), + int chosen = JOptionPane.showOptionDialog(this.getFrame(), parser.error, Menu.msgTitleParserError.getText(), JOptionPane.YES_NO_OPTION, @@ -6572,7 +6590,7 @@ else if (logPath.equals(".")) { } } catch (java.util.concurrent.CancellationException ex) { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgImportCancelled.getText().replace("%", file.getPath())); } catch(Exception ex) @@ -6586,7 +6604,7 @@ else if (logPath.equals(".")) { // END KGU#484 2018-04-05 } if (message == null || message.isEmpty()) message = ex.toString(); - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgErrorUsingParser.getText().replace("%", parser.getDialogTitle())+"\n" + message, Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE); @@ -6691,7 +6709,7 @@ private void retrieveParsers() { } if (!errors.isEmpty()) { errors = Menu.msgTitleLoadingError.getText() + errors; - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), errors, + JOptionPane.showMessageDialog(this.getFrame(), errors, Menu.msgTitleParserError.getText(), JOptionPane.ERROR_MESSAGE); } } @@ -6752,7 +6770,7 @@ public void export(String _generatorClassName, Vector> _ if (thisGenName.equals(this.lastGeneratorName)) { if (++this.generatorUseCount == this.generatorProposalTrigger && this.generatorProposalTrigger > 0 && !prefGenName.equals(this.lastGeneratorName)) { - if (JOptionPane.showConfirmDialog(this.NSDControl.getFrame(), + if (JOptionPane.showConfirmDialog(this.getFrame(), Menu.msgSetAsPreferredGenerator.getText().replace("%1", thisGenName).replaceAll("%2", Integer.toString(this.generatorUseCount)), Menu.lbFileExportCodeFavorite.getText().replace("%", thisGenName), JOptionPane.YES_NO_OPTION, @@ -6779,7 +6797,7 @@ public void export(String _generatorClassName, Vector> _ String message = ex.getLocalizedMessage(); if (message == null) message = ex.getMessage(); if (message == null || message.isEmpty()) message = ex.toString(); - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgErrorUsingGenerator.getText().replace("%", _generatorClassName)+"\n" + message, Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE); @@ -6825,7 +6843,7 @@ public void updateCodePreview() String message = ex.getLocalizedMessage(); if (message == null) message = ex.getMessage(); if (message == null || message.isEmpty()) message = ex.toString(); - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgErrorUsingGenerator.getText().replace("%", generatorName)+"\n" + message, Menu.msgTitleError.getText(), JOptionPane.ERROR_MESSAGE); @@ -7096,7 +7114,7 @@ public void hyperlinkUpdate(HyperlinkEvent evt) JLabel label = new JLabel(); ep.setBackground(label.getBackground()); - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), ep); + JOptionPane.showMessageDialog(this.getFrame(), ep); } catch(Exception e) { @@ -7588,7 +7606,7 @@ public boolean offerRefactoring(HashMap refactoringData) //if (answer != 0 && answer != JOptionPane.CLOSED_OPTION) int answer = JOptionPane.CLOSED_OPTION; do { - answer = JOptionPane.showOptionDialog(this.NSDControl.getFrame(), + answer = JOptionPane.showOptionDialog(this.getFrame(), // START KGU#719 2019-08-01 //Menu.msgRefactoringOffer.getText().replace("%", "\n" + replacements.getText() + "\n"), box, @@ -7597,7 +7615,7 @@ public boolean offerRefactoring(HashMap refactoringData) JOptionPane.QUESTION_MESSAGE, null, options, options[2]); - if (answer == JOptionPane.CLOSED_OPTION && JOptionPane.showConfirmDialog(this.NSDControl.getFrame(), + if (answer == JOptionPane.CLOSED_OPTION && JOptionPane.showConfirmDialog(this.getFrame(), Menu.msgDiscardParserPrefs.getText()) == JOptionPane.OK_OPTION) { // Revert the changes for (Map.Entry refEntry: refactoringData.entrySet()) { @@ -7636,7 +7654,7 @@ private void offerStructPrefAdaptation(HashMap refactoringDa (updateNeed = checkPref(Element.preRepeat, refactoringData, "preRepeat", "postRepeat")) != null || (updateNeed = checkPrefCase(Element.preCase, refactoringData)) != null || (updateNeed = checkPrefFor(Element.preFor, refactoringData)) != null) - && JOptionPane.showConfirmDialog(this.NSDControl.getFrame(), + && JOptionPane.showConfirmDialog(this.getFrame(), Menu.msgAdaptStructPrefs.getText().replace("%", updateNeed), Menu.msgTitleQuestion.getText(), JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) { // END KGU#735 2019-09-29 @@ -8733,7 +8751,7 @@ public void configureWheelUnit() JSpinner spnUnit = new JSpinner(); spnUnit.setModel(new SpinnerNumberModel(Math.max(1, Element.E_WHEEL_SCROLL_UNIT), 1, 20, 1)); spnUnit.addMouseWheelListener(this); - if (JOptionPane.showConfirmDialog(this.NSDControl.getFrame(), + if (JOptionPane.showConfirmDialog(this.getFrame(), spnUnit, Menu.ttlMouseScrollUnit.getText(), JOptionPane.OK_CANCEL_OPTION, @@ -8795,11 +8813,17 @@ public void setPreferredGeneratorName(String genName) for (GENPlugin plugin: Menu.generatorPlugins) { if (genName.equalsIgnoreCase(plugin.title)) { ini.load(); - if (!genName.equalsIgnoreCase(this.prefGeneratorName)) { - this.generatorUseCount = 1; - } - this.prefGeneratorName = plugin.title; - if (!this.prefGeneratorName.equals(ini.getProperty("genExportPreferred", "Java"))) { + // START KGU#764 2019-11-29: Issue #777 - Another Sructorizer instance may have changed the favourite language + //if (!genName.equalsIgnoreCase(this.prefGeneratorName)) { + // this.generatorUseCount = 1; + //} + //this.prefGeneratorName = plugin.title; + //if (!this.prefGeneratorName.equals(ini.getProperty("genExportPreferred", "Java"))) { + String iniGeneratorName = ini.getProperty("genExportPreferred", this.prefGeneratorName); + boolean modified = !genName.equalsIgnoreCase(this.prefGeneratorName) || !genName.equalsIgnoreCase(iniGeneratorName); + if (modified) { + this.prefGeneratorName = plugin.title; + // END KGU#764 2019-11-29 ini.setProperty("genExportPreferred", plugin.title); ini.save(); updateCodePreview(); @@ -9465,7 +9489,7 @@ protected ArrayList getDiagramControllers() { } if (!errors.isEmpty()) { errors = Menu.msgTitleLoadingError.getText() + errors; - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), errors, + JOptionPane.showMessageDialog(this.getFrame(), errors, Menu.msgTitleParserError.getText(), JOptionPane.ERROR_MESSAGE); } return diagramControllers; @@ -9848,7 +9872,7 @@ public void attributesNSD() public void inspectAttributes(Root _root) { RootAttributes licInfo = new RootAttributes(_root); AttributeInspector attrInsp = new AttributeInspector( - this.NSDControl.getFrame(), licInfo); + this.getFrame(), licInfo); pop.setVisible(false); // Issue #143: Hide the current comment popup if visible attrInsp.setVisible(true); if (attrInsp.isCommitted()) { @@ -10010,7 +10034,7 @@ public void setInitialized() { // START KGU#459 2017-11-14: Enh. #459-1 public void showTutorialHint() { - JOptionPane.showMessageDialog(this.NSDControl.getFrame(), + JOptionPane.showMessageDialog(this.getFrame(), Menu.msgGuidedTours.getText(), Menu.ttlGuidedTours.getText(), JOptionPane.INFORMATION_MESSAGE, @@ -10056,7 +10080,7 @@ public void setHideDeclarations(boolean _activate) { * localization. */ public void elementNamesNSD() { - ElementNamePreferences namePrefs = new ElementNamePreferences(this.NSDControl.getFrame()); + ElementNamePreferences namePrefs = new ElementNamePreferences(this.getFrame()); for (int i = 0; i < namePrefs.txtElements.length; i++) { namePrefs.txtElements[i].setText(ElementNames.configuredNames[i]); } @@ -10115,7 +10139,7 @@ public boolean enableController(String className, boolean selected) */ public void controllerAliasesNSD(Vector controllerPlugins) { - DiagramControllerAliases dialog = new DiagramControllerAliases(this.NSDControl.getFrame(), controllerPlugins); + DiagramControllerAliases dialog = new DiagramControllerAliases(this.getFrame(), controllerPlugins); dialog.setVisible(true); // FIXME: Just temporary - mind Element.controllerName2Alias and Element.controllerAlias2Name if (dialog.OK) { @@ -10143,9 +10167,14 @@ public void setApplyAliases(boolean apply) { // END KGU#480 2018-01-18 // START KGU#356 2019-03-14: Issue #366 - /** @return the owning @{@link JFrame} (actually the {@link Mainform}) */ + /** @return the owning @{@link JFrame} (actually the {@link Mainform}) or null */ public JFrame getFrame() { + // START KGU 2019-11-24: Make sure this doesn't cause a NullPointerException + if (this.NSDControl == null) { + return null; + } + // END KGU 2019-11-24 return this.NSDControl.getFrame(); } // END KGU#356 2019-03-14 @@ -10234,7 +10263,7 @@ public void actionPerformed(ActionEvent e) { panel.add(new JSeparator(SwingConstants.HORIZONTAL)); panel.add(panel2); GUIScaler.rescaleComponents(panel); - if (JOptionPane.showConfirmDialog(this.NSDControl.getFrame(), panel, title, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { + if (JOptionPane.showConfirmDialog(this.getFrame(), panel, title, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { keys = new HashSet(); if (!chkAll.isSelected()) { i = 0; diff --git a/src/lu/fisch/structorizer/gui/InputBoxRoot.java b/src/lu/fisch/structorizer/gui/InputBoxRoot.java index f2df17dc..505b4955 100644 --- a/src/lu/fisch/structorizer/gui/InputBoxRoot.java +++ b/src/lu/fisch/structorizer/gui/InputBoxRoot.java @@ -45,7 +45,6 @@ * ******************************************************************************************************/// -import java.awt.Dimension; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; diff --git a/src/lu/fisch/structorizer/gui/Menu.java b/src/lu/fisch/structorizer/gui/Menu.java index 16f8b20f..889f2351 100644 --- a/src/lu/fisch/structorizer/gui/Menu.java +++ b/src/lu/fisch/structorizer/gui/Menu.java @@ -559,8 +559,10 @@ public enum PluginType { GENERATOR, PARSER, IMPORTER, CONTROLLER }; new LangTextHolder("Now you may e.g. export your diagram as graphics file: → Menu \"%1 ► %2 ► %3\"") }; // END KGU#456 2017-11-01 - public static final LangTextHolder error27 = new LangTextHolder("Some selector item seems not to be an integer constant."); + // START KGU#758 2019-11-08: Enh. #770 + public static final LangTextHolder error27 = new LangTextHolder("Some selector items (e.g. «%») don't seem to be integer constants."); public static final LangTextHolder error28 = new LangTextHolder("There are multiple (conflicting) selector items (%) in the CASE element!"); + // END KGU#758 2019-11-08 // START KGU#459 2017-11-14: Enh. #459 public static final LangTextHolder msgGuidedTours = new LangTextHolder("You activated guided tours.\n\nWatch out for recommendations\nor instructions\nin the bottom text pane\n(Analyser report list)."); public static final LangTextHolder msgGuidedTourDone = new LangTextHolder("Congratulations - you finished the tutorial «%»."); diff --git a/src/lu/fisch/structorizer/gui/OSXAdapter.java b/src/lu/fisch/structorizer/gui/OSXAdapter.java index e25f32f9..bee5e100 100644 --- a/src/lu/fisch/structorizer/gui/OSXAdapter.java +++ b/src/lu/fisch/structorizer/gui/OSXAdapter.java @@ -134,7 +134,7 @@ public boolean callTarget(Object appleEvent) { public static void setDockIconImage(Image image) { try { - Class applicationClass = Class.forName("com.apple.eawt.Application"); + Class applicationClass = Class.forName("com.apple.eawt.Application"); if (macOSXApplication == null) { macOSXApplication = applicationClass.getConstructor((Class[])null).newInstance((Object[])null); } @@ -151,11 +151,11 @@ public static void setDockIconImage(Image image) // setHandler creates a Proxy object from the passed OSXAdapter and adds it as an ApplicationListener public static void setHandler(OSXAdapter adapter) { try { - Class applicationClass = Class.forName("com.apple.eawt.Application"); + Class applicationClass = Class.forName("com.apple.eawt.Application"); if (macOSXApplication == null) { macOSXApplication = applicationClass.getConstructor((Class[])null).newInstance((Object[])null); } - Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener"); + Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener"); Method addListenerMethod = applicationClass.getDeclaredMethod("addApplicationListener", new Class[] { applicationListenerClass }); // Create a proxy object around this handler that can be reflectively added as an Apple ApplicationListener Object osxAdapterProxy = Proxy.newProxyInstance(OSXAdapter.class.getClassLoader(), new Class[] { applicationListenerClass }, adapter); diff --git a/src/lu/fisch/structorizer/gui/changelog.txt b/src/lu/fisch/structorizer/gui/changelog.txt index bbe78140..1b5c5155 100644 --- a/src/lu/fisch/structorizer/gui/changelog.txt +++ b/src/lu/fisch/structorizer/gui/changelog.txt @@ -10,8 +10,9 @@ Known issues: - COBOL import may fail if certain single-letter identifiers are used (rename them!). - COBOL import doesn't cope with some statement variants and variable redefinitions. - The Javascript generator is just a prototype and may be deficient. +- Shell export does not cope with nested array/record initializers and component access. -Current development version: 3.30-02 (2019-11-12) +Current development version: 3.30-03 (2019-12-02) - 01: Bugfix #759: Another source of stale Mainforms dried up. <2> - 01: Bugfix #761: Code preview defect flooded the log stream. <2> - 01: Precautions against empty error messages on startup <2> @@ -27,6 +28,26 @@ Current development version: 3.30-02 (2019-11-12) - 02: Bugfix #771: Unhandled syntax errors during execution (e.g. type names) <2> - 02: Bugfix #772: Possible NullPointerException averting Pascal code preview <2> - 02: Bugfix #773: Export of declarations to Oberon, Pascal [K.-P. Reimers]2 +- 03: Enh. #388: Support for constants on Perl export (had been missing) <2> +- 03: Enh. #423: Support for record types on Perl export (had been missing) <2> +- 03: Enh. #739: Enum type definitions introduced (incl. C99, Pascal import) <2> +- 03: Issue #766: Deterministic export order had not worked for deep hierarchies <2> +- 03: Bugfix #770: Not all CASE selectors were checked to be constant integers <2> +- 03: Enh. #775: More type-sensitive export of input instructions to OBERON <2> +- 03: Bugfix #776: Global variables are locally eclipsed on Pascal/Oberon export <2> +- 03: Bugfix #777: Concurrently changed favourite export language handled. <2> +- 03: Bugfix #778: License text was not exported with "fresh" diagrams <2> +- 03: Bugfix #779: Defective Oberon export of main program diagrams with I/O <2> +- 03: Issue #780: Parameterless procedures in Oberon without parentheses [K.-P. R.]2 +- 03: Bugfix #782: Code export of global (included) declarations was wrong. <2> +- 03: Bugfix #783: No or nonsense code export for assignments of unknown structs <2> +- 03: Bugfix #784: Suppression of mere variable declarations on bash/ksh export <2> +- 03: Bugfix #786: Record access in index expressions used to fail on execution <2> +- 03: Bugfix #787: Multiplied top-level type definitions on Pascal export <2> +- 03: Bugfix #788: Arrz file extraction to a user-specific folder did not work. <2> +- 03: Bugfix #789: Wrong BASIC export of function calls (started with "CALL") <2> +- 03: Bugfix #790: BASIC export failed with line continuation and initializers <2> +- 03: Bugfix #791: Shell export flaws (function calls, array/assoc declarators) <2> Version: 3.30 (2019-10-06) - 01: Issue #657: Spanish message in German locale replaced <2> diff --git a/src/lu/fisch/structorizer/locales/de.txt b/src/lu/fisch/structorizer/locales/de.txt index 5533f28d..b4c93a06 100644 --- a/src/lu/fisch/structorizer/locales/de.txt +++ b/src/lu/fisch/structorizer/locales/de.txt @@ -536,7 +536,7 @@ Menu.hint26.1.text=Jetzt können Sie z.B. Ihr Diagramm testen → Menu "%1 ► % Menu.hint26.2.text=Jetzt können Sie z.B. Ihr Diagramm speichern → Menu "%1 ► %2" Menu.hint26.3.text=Jetzt können Sie z.B. Ihr Diagramm in eine Programmiersprache exportieren → Menu "%1 ► %2 ► %3" Menu.hint26.4.text=Jetzt können Sie z.B. Ihr Diagramm als Grafikdatei exportieren → Menu "%1 ► %2 ► %3" -Menu.error27.text=Einige Auswahlwerte scheinen keine Ganzzahlkonstante zu sein. +Menu.error27.text=Einige Auswahlwerte (z.B. «%») scheinen keine Ganzzahlkonstanten zu sein. Menu.error28.text=Einige Werte (%) kommen mehrfach in den Auswahllisten vor! Menu.errorLineReference.text= (Zeile %) diff --git a/src/lu/fisch/structorizer/locales/en.txt b/src/lu/fisch/structorizer/locales/en.txt index 128176d5..1aac3960 100644 --- a/src/lu/fisch/structorizer/locales/en.txt +++ b/src/lu/fisch/structorizer/locales/en.txt @@ -534,7 +534,7 @@ Menu.hint26.1.text=Now you may e.g. test your diagram: → Menu "%1 ► %2" Menu.hint26.2.text=Now you may e.g. save your diagram: → Menu "%1 ► %2" Menu.hint26.3.text=Now you may e.g. export your diagram to some programming language: → Menu "%1 ► %2 ► %3" Menu.hint26.4.text=Now you may e.g. export your diagram as graphics file: → Menu "%1 ► %2 ► %3" -Menu.error27.text=Some @c selector items don't seem to be integer constants. +Menu.error27.text=Some @c selector items (e.g. «%») don't seem to be integer constants. Menu.error28.text=There are multiple (conflicting) selector items (%) in the @c element! Menu.errorLineReference.text= (line %) diff --git a/src/lu/fisch/structorizer/locales/es.txt b/src/lu/fisch/structorizer/locales/es.txt index 3dabcd4e..be067023 100644 --- a/src/lu/fisch/structorizer/locales/es.txt +++ b/src/lu/fisch/structorizer/locales/es.txt @@ -538,7 +538,7 @@ Menu.hint26.1.text=Ahora puedes p.ej. probar tu diagrama: → Menú "%1 ► %2" Menu.hint26.2.text=Ahora puedes p.ej. grabar tu diagrama: → Menú "%1 ► %2" Menu.hint26.3.text=Ahora puedes p.ej. exportar tu diagrama a un código: → Menú "%1 ► %2 ► %3" Menu.hint26.4.text=Ahora puedes p.ej. exportar tu diagrama como imágen: → Menú "%1 ► %2 ► %3" -Menu.error27.text=Algunos valores comparativos @c no parecen constantes integrales. +Menu.error27.text=Algunos valores comparativos @c (p.ej. «%») no parecen constantes integrales. Menu.error28.text=!Valores comparativos (%) ocurren varias veces o en más de un ramo del elemento @c! Menu.errorLineReference.text= (línea %) diff --git a/src/lu/fisch/structorizer/locales/nl.txt b/src/lu/fisch/structorizer/locales/nl.txt index 64f71d10..28e3ef0b 100644 --- a/src/lu/fisch/structorizer/locales/nl.txt +++ b/src/lu/fisch/structorizer/locales/nl.txt @@ -463,6 +463,8 @@ Menu.hint26.1.text=U kunt nu bijv. uw diagram uitproberen: → Menu "%1 ► %2" Menu.hint26.2.text=U kunt nu bijv. uw diagram opslaan: → Menu "%1 ► %2" Menu.hint26.3.text=U kunt nu bijv. uw diagram exporteren naar een programmeertaal: → Menu "%1 ► %2 ► %3" Menu.hint26.4.text=U kunt nu bijv. uw diagram exporteren als afbeeldingsbestand: → Menu "%1 ► %2 ► %3" +Menu.error27.text=Enkele keuzewaarden (zoals «%») lijken geen gehele getallen te zijn. +Menu.error28.text=Enkele waarden (%) komen vaker voor in de (meerdere) keuzelijsten! Menu.errorLineReference.text=(regel %) -----[ AnalyserPreferences ]----- @@ -496,6 +498,8 @@ AnalyserPreferences.checkboxes.23.text=Controle op verkeerde importen van diagra AnalyserPreferences.checkboxes.24.text=Controle op type-definities en toegang tot record-componenten. AnalyserPreferences.checkboxes.25.text=Gids voor de eerste programma-instructies (IPO-model) AnalyserPreferences.checkboxes.26.text=Korte rondleiding "hallo wereld" +AnalyserPreferences.checkboxes.27.text=Controle of de keuzewaarden gehele getallen zijn. +AnalyserPreferences.checkboxes.28.text=Controle of de keuzelijsten gemeenschappelijke elementen hebben. AnalyserPreferences.okButton.text=OK @@ -1231,7 +1235,7 @@ Surface.msgUnsavedGroups.text=Kon deze groepen (rangschikkingen) niet opslaan: Surface.msgDiagram.text=diagram «%» Surface.msgGroup.text=groep «%» Surface.msgGroupExists.text=Groep met naam «%» bestaat al! -Surface.titleRenameGroup.text=Groeo "%1" hernoemen naar "%2"? +Surface.titleRenameGroup.text=Groep "%1" hernoemen naar "%2"? Surface.msgRenameArrFile.text=Rangschikkingsbestand\n"%1"\nto "%2"? Surface.msgRenamingFailed.text=Kon rangschikkingsbestand niet hernoemen naar "%"!\nActie wordt geannuleerd. Surface.msgSharedDiagrams.text=De volgende diagrammen worden nu gedeeld met de groepen in de lijst\n - %1\n\nLet erop dat elke verandering erin invloed heeft op al deze groepen\nen archief %2, ook al is deze laatste niet meer ingelzen! diff --git a/src/lu/fisch/structorizer/locales/ru.txt b/src/lu/fisch/structorizer/locales/ru.txt index f24c93c2..d0f0bc0c 100644 --- a/src/lu/fisch/structorizer/locales/ru.txt +++ b/src/lu/fisch/structorizer/locales/ru.txt @@ -477,6 +477,8 @@ Menu.hint26.1.text= Menu.hint26.2.text= Menu.hint26.3.text= Menu.hint26.4.text= +Menu.error27.text=Некоторые показатели выбора (напр. «%») не являются целочисленными постоянными. +Menu.error28.text=Некоторые показатели выбора (%) стоят над различными ветками! Menu.errorLineReference.text=(строка %) -----[ AnalyserPreferences ]----- @@ -510,6 +512,8 @@ AnalyserPreferences.checkboxes.23.text= AnalyserPreferences.checkboxes.24.text= AnalyserPreferences.checkboxes.25.text= AnalyserPreferences.checkboxes.26.text=Краткий курс "Привет, мир!" +AnalyserPreferences.checkboxes.27.text=Проверять что @c показатели являются целочисленными постоянными. +AnalyserPreferences.checkboxes.28.text=Проверять что @c показатели не стоят над различными ветками. AnalyserPreferences.okButton.text=ОК diff --git a/src/lu/fisch/structorizer/parsers/C99Parser.java b/src/lu/fisch/structorizer/parsers/C99Parser.java index c64cde97..924fa604 100644 --- a/src/lu/fisch/structorizer/parsers/C99Parser.java +++ b/src/lu/fisch/structorizer/parsers/C99Parser.java @@ -56,6 +56,7 @@ * Kay Gürtzig 2019-02-28 Bugfix #690 - workaround for struct types in function headers * Kay Gürtzig 2019-03-01 Bugfix #692 - failed constant recognition * Kay Gürtzig 2019-03-29 KGU#702: Index range exception in method getPointers() fixed. + * Kay Gürtzig 2019-11-18 Enh. #739: Direct enum type import * ****************************************************************************************************** * @@ -1978,23 +1979,41 @@ else if (!prefixStr.equals("auto") && !isTypedef) { if (names.count() > 0 && _parentNode != null) { names = names.reverse(); values = values.reverse(); - int val = 0; - String baseVal = ""; + //int val = 0; + //String baseVal = ""; for (int i = 0; i < names.count(); i++) { - if (!values.get(i).isEmpty()) { - baseVal = values.get(i); - try { - val = Integer.parseInt(baseVal); - baseVal = ""; // If the value was an int literal, we don't need an expr. string - } - catch (NumberFormatException ex) { - val = 0; - } + // START KGU#542 2019-11-18: Enh. #739 - true enum type import + //if (!values.get(i).isEmpty()) { + // baseVal = values.get(i); + // try { + // val = Integer.parseInt(baseVal); + // baseVal = ""; // If the value was an int literal, we don't need an expr. string + // } + // catch (NumberFormatException ex) { + // val = 0; + // } + //} + //names.set(i, "const " + names.get(i) + " <- " + baseVal + (baseVal.isEmpty() ? "" : " + ") + val); + //val++; + String valStr = values.get(i).trim(); + if (!valStr.isEmpty()) { + names.set(i, names.get(i) + " = " + valStr); } - names.set(i, "const " + names.get(i) + " <- " + baseVal + (baseVal.isEmpty() ? "" : " + ") + val); - val++; + // END KGU#542 2019-11-18 + } + // START KGU#542 2019-11-18: Enh. #739 + //Instruction enumDef = new Instruction(names); + String sepa = ", "; + // FIXME: Tune the threshold if necessary + if (names.count() > 10) { + sepa = ",\\\n"; + } + if (typeName == null) { + typeName = "Enum" + Math.abs(System.nanoTime()); } - Instruction enumDef = new Instruction(names); + Instruction enumDef = new Instruction( + StringList.explode("type " + typeName + " = enum{" + names.concatenate(sepa) + "}", "\n")); + // END KGU#542 2019-11-18 this.equipWithSourceComment(enumDef, prefix.asReduction()); if (typeName != null) { enumDef.getComment().add("Enumeration type " + typeName); diff --git a/src/lu/fisch/structorizer/parsers/D7Parser.java b/src/lu/fisch/structorizer/parsers/D7Parser.java index 2b47678d..7b534d34 100644 --- a/src/lu/fisch/structorizer/parsers/D7Parser.java +++ b/src/lu/fisch/structorizer/parsers/D7Parser.java @@ -65,6 +65,7 @@ * Bugfix #614: Redundant result assignments in function diagrams removed * Workaround #615: Replace comment delimiters (* *) with { } in preparation phase * Kay Gürtzig 2019-03-23 Enh. #56: Import of Try and Raise instructions implemented. + * Kay Gürtzig 2019-11-19 Enh. #739: Genuine enumeration type import (revision of #558) * ****************************************************************************************************** * @@ -1272,7 +1273,9 @@ else if ( _parentNode.addElement(def); if (isEnum) { def.setColor(colorConst); - def.getComment().add("Enumerator type " + typeName); + // START KGU#542 2019-11-19: Enh. #739 - No longer needed, now genuine enum type import + //def.getComment().add("Enumerator type " + typeName); + // END KGU#542 2019-11-19 } } } @@ -1782,6 +1785,14 @@ private String insertExceptionBlock(Case _case, Reduction _exStmtReduction, Stri } // START KGU#542 2018-07-11: Enh. #558 - provisional enum type support + /** + * Returns the complete instruction element content for an enumeration type + * definition represented by the {@link Reduction} {@code redEnumL} + * @param redEnumL - the enumeration reduction to be analysed + * @param typeName - actually more than just the type name but "type <typename&rt; = ". + * @return the text content for the {@link Instruction} element to be created + * @throws ParserCancelled in case of an interactive user abort + */ private String importEnumType(Reduction redEnumL, String typeName) throws ParserCancelled { StringList names = new StringList(); StringList values = new StringList(); @@ -1806,24 +1817,38 @@ private String importEnumType(Reduction redEnumL, String typeName) throws Parser if (names.count() > 0) { names = names.reverse(); values = values.reverse(); - int val = 0; - String baseVal = ""; + //int val = 0; + //String baseVal = ""; for (int i = 0; i < names.count(); i++) { - if (!values.get(i).isEmpty()) { - baseVal = values.get(i); - try { - val = Integer.parseInt(baseVal); - baseVal = ""; // If the value was an int literal, we don't need an expr. string - } - catch (NumberFormatException ex) { - val = 0; - } + // START KGU#542 2019-11-19: Enh. #739 - true enum type import + //if (!values.get(i).isEmpty()) { + // baseVal = values.get(i); + // try { + // val = Integer.parseInt(baseVal); + // baseVal = ""; // If the value was an int literal, we don't need an expr. string + // } + // catch (NumberFormatException ex) { + // val = 0; + // } + //} + //names.set(i, "const " + names.get(i) + " <- " + baseVal + (baseVal.isEmpty() ? "" : " + ") + val); + //val++; + String valStr = values.get(i).trim(); + if (!valStr.isEmpty()) { + names.set(i, names.get(i) + " = " + valStr); } - names.set(i, "const " + names.get(i) + " <- " + baseVal + (baseVal.isEmpty() ? "" : " + ") + val); - val++; + // END KGU#542 2019-11-19 } } - return names.concatenate("\n"); + // START KGU#542 2019-11-18: Enh. #739 + //return names.concatenate("\n"); + String sepa = ", "; + // FIXME: Tune the threshold if necessary + if (names.count() > 10) { + sepa = ",\\\n"; + } + return typeName + "enum{" + names.concatenate(sepa) + "}"; + // END KGU#542 2019-11-19 } // END KGU#542 2018-07-11 diff --git a/src/lu/fisch/utils/BString.java b/src/lu/fisch/utils/BString.java index 37ef0a49..1fa6c796 100644 --- a/src/lu/fisch/utils/BString.java +++ b/src/lu/fisch/utils/BString.java @@ -32,16 +32,17 @@ * * Author Date Description * ------ ---- ----------- - * Bob Fisch 2003.05.10 First Issue - * Bob Fisch 2007.12.09 Moved to another package and adapted for Structorizer - * Kay Gürtzig 2015.10.31 Performance improvements - * Kay Gürtzig 2017.03.13 New method pair encodeToXML and decodeFromXML added for enh. #372, + * Bob Fisch 2003-05-10 First Issue + * Bob Fisch 2007-12-09 Moved to another package and adapted for Structorizer + * Kay Gürtzig 2015-10-31 Performance improvements + * Kay Gürtzig 2017-03-13 New method pair encodeToXML and decodeFromXML added for enh. #372, * Some code revisions where it ached too much looking at. - * Kay Gürtzig 2017.06.18 Method breakup refined to cope with meta symbols in the string to + * Kay Gürtzig 2017-06-18 Method breakup refined to cope with meta symbols in the string to * be broken up for regex matching. Code revision, several redundant * methods declared as deprecated - * Kay Gürtzig 2017.11.03 Bugfix #448: Method breakup(String) revised again - * Kay Gürtzig 2018.09.12 Method name typo refactored: enocodeVectorToHtml() --> encodeVectorToHtml() + * Kay Gürtzig 2017-11-03 Bugfix #448: Method breakup(String) revised again + * Kay Gürtzig 2018-09-12 Method name typo refactored: enocodeVectorToHtml() --> encodeVectorToHtml() + * Kay Gürtzig 2019-11-22 Dead code in encodeToHtml() disabled, bugfix in explode() * ****************************************************************************************************** * @@ -73,15 +74,16 @@ public static String encodeToHtml(String str) str = str.replace("\"","""); //str=BString.replace(str," "," "); - // FIXME (KGU): The following code is irrelevant for the result! Should we return res (if not null)? - String res = null; - try { - byte[] utf8 = str.getBytes("UTF-8"); - res = new String(utf8, "UTF-8"); - } - catch (Exception e) - { - } + // START KGU 2019-11-22: The following code was irrelevant for the result! Should we have return res (if not null)? + //String res = null; + //try { + // byte[] utf8 = str.getBytes("UTF-8"); + // res = new String(utf8, "UTF-8"); + //} + //catch (Exception e) + //{ + //} + // END KGU 2019-11-22 return str; } @@ -214,7 +216,7 @@ public static Vector encodeVectorToHtml(Vector vec) /** * Cuts blanks at the end and at the beginning of the string. [trim]
- * NOTE: You should better use {@code str.trim()} instead. + * NOTE: You should better use {@link String#trim()} instead. *@param str - The string to be trimmed *@return The trimmed string */ @@ -227,7 +229,7 @@ public static String cutOut(String str) /** * Checks whether a string contains any non-blank characters
* NOTE: You may use {@code !str.trim().isEmpty()} instead - *@param str The string to check + *@param str - The string to check *@return true iff there is at least one non-blank character */ @Deprecated @@ -249,7 +251,7 @@ public static boolean containsSomething(String str) /** * Replaces all substrings with another substring
- * NOTE: You should better use {@code str.replace(substr, with)} instead. + * NOTE: You should better use {@link String#replace(CharSequence, CharSequence)} instead. *@param str The original string *@param substr The substring to be replaced *@param with The substring to put in @@ -278,7 +280,8 @@ public static String replace(String str, String substr, String with) } /** - * Replaces all substrings with another substring + * Replaces all substrings {@code substr} in string {@code str} with another + * substring {@code with}. *@return The replaced string *@param str The original string *@param substr The substring to be replaced @@ -309,7 +312,7 @@ public static String replaceInsensitive(String str, String substr, String with) } /** - * Checks that the character codes of string s are strictly monotonous, + * Checks that the character codes of string {@code s} are strictly monotonous, * i.e. i ≤ j --> s[i] ≤ s[j], but not all equal (if there are * at least two characters). * @param s - the string to be analysed @@ -342,6 +345,7 @@ public static boolean croissantStrict(String s) * @param pre - the prefix to be confirmed * @param str - the analysed string * @return true iff {@code str} starts with prefix {@code pre} + * @see String#startsWith(String) */ @Deprecated public static boolean isPrefixOf(String pre, String str) @@ -361,27 +365,33 @@ public static boolean isPrefixOf(String pre, String str) /** * Splits the string {@code _source} around occurrences of delimiter string {@code _by} - * and returns a StringList consisting of the split parts (without the separating + * and returns a {@link StringList} consisting of the split parts (without the separating * delimiters) in order of occurrence.
* @param _source - the string to be split * @param _by - the separating string (not interpreted as regular expression!) * @return the split result + * @see StringList#explode(String, String) + * @see String#explodeWithDelimiter(String, String) */ public static StringList explode(String _source, String _by) { StringList sl = new StringList(); - while(!_source.equals("")) + while (!_source.isEmpty()) { - if (_source.indexOf(_by)>=0) + int posBy = _source.indexOf(_by); + if (posBy >= 0) { - sl.add(_source.substring(0,_source.indexOf(_by)-1)); - _source=_source.substring(_source.indexOf(_by)+_by.length(), _source.length()); + // START KGU 2019-11-22 Wrong cut position + //sl.add(_source.substring(0,_source.indexOf(_by)-1)); + sl.add(_source.substring(0, posBy)); + // END KGU 2019-11-22 + _source=_source.substring(posBy + _by.length()); } else { sl.add(_source); - _source=""; + _source = ""; } } return sl; @@ -391,10 +401,11 @@ public static StringList explode(String _source, String _by) * Splits the string {@code _source} around occurrences of delimiter string {@code _by} * and returns a StringList consisting of the split parts and the separating * delimiters in order of occurrence.
- * NOTE: Use method {@code explodeWithDElimiter(String, String)} on {@link #StringList} instead. + * NOTE: Use method {@link StringList#explodeWithDelimiter(String, String)} instead. * @param _source - the string to be split * @param _by - the separating string * @return the split result + * @see String#explodeWithDelimiter(String, String) */ @Deprecated public static StringList explodeWithDelimiter(String _source, String _by) diff --git a/src/lu/fisch/utils/StringList.java b/src/lu/fisch/utils/StringList.java index 74ebe184..de267845 100644 --- a/src/lu/fisch/utils/StringList.java +++ b/src/lu/fisch/utils/StringList.java @@ -50,6 +50,7 @@ * Kay Gürtzig 2019-02-15 Method isEmpty() added * Kay Gürtzig 2019-03-03 Bugfix in method explodeFirstOnly(String, String) * Kay Gürtzig 2019-03-05 New method variants explodeWithDelimiter() for case-independent splitting + * Kay Gürtzig 2019-11-20 New methods count(String), count(String, boolean), insert(StringList, int) * ****************************************************************************************************** * @@ -757,19 +758,48 @@ public String get(int _index) } } + /** + * Removes the {@code _index}th element from the StringList. + * @param _index - the position of the element to be removed + * @throws ArrayIndexOutOfBoundsException if {@code _index} is out of range (_index < 0 || _index >= count()) + */ public void delete(int _index) { strings.removeElementAt(_index); } + /** + * Inserts the given string {@code _string} into this StringList before position {@code _index}. + * Throws an exception if _index is negative or larger than the current length. + * @param _strList - the StringList to be inserted + * @param _index - the insertion index + * @throws ArrayIndexOutOfBoundsException if {@code _index} is out of range (_index < 0 || _index > count()) + */ public void insert(String _string, int _index) { strings.insertElementAt(_string,_index); } + + /** + * Inserts the series of copies of all elements of {@code _strList} into + * this StringList before position {@code _index}. Throws an exception if _index + * is negative or larger than the current length. + * @param _strList - the StringList to be inserted + * @param _index - the insertion index + * @throws ArrayIndexOutOfBoundsException if {@code _index} is out of range (_index < 0 || _index > count()) + */ + public void insert(StringList _strList, int _index) + { + if (_index >= 0 && _index <= strings.size() && !_strList.isEmpty()) { + for (int i = 0; i < _strList.count(); i++) { + strings.insertElementAt(_strList.get(i), _index++); + } + } + } public void setText(String _text) { - String[] lines = _text.split ("\n"); + String[] lines = _text.split("\n"); strings.clear(); for (int i=0; i < lines.length; i++) { @@ -813,9 +843,9 @@ public String concatenate(String _separator, int _start, int _end) boolean lastEndedLikeId = false; // END KGU#425 2017-09-29 boolean isFirst = true; - for(int i = Math.min(_start, count()); i < Math.min(_end, count()); i++) + for(int i = Math.min(_start, count()); i < Math.min(_end, count()); i++) { - String thisString = strings.get(i); + String thisString = strings.get(i); if (isFirst) { //text = strings.get(i); @@ -843,7 +873,7 @@ else if (!thisString.isEmpty()) { text.append(thisString); } //return text; - return text.toString(); + return text.toString(); } public String concatenate(String _separator, int _start) @@ -889,6 +919,34 @@ public int count() return strings.size(); } + /** + * Counts the occurrences of the given string {@code str} among the elements + * @param str - the string to search for + * @return the number of occurrences + * @see #count(String, boolean) + */ + public int count(String _str) + { + return this.count(_str, true); + } + + /** + * Counts the occurrences of the given string {@code str} among the elements + * @param str - the string to search for + * @param matchCase - whether upper/lower case should make a difference + * @return the number of occurrences + */ + public int count(String _str, boolean _matchCase) + { + int cnt = 0; + for (String elem: this.strings) { + if (_matchCase && elem.equals(_str) || !_matchCase && elem.equalsIgnoreCase(_str)) { + cnt++; + } + } + return cnt; + } + /** * Tests if this StringList has no components * @return {@code true} if and only if this StringList has no elements. diff --git a/src/net/iharder/dnd/FileDrop.java b/src/net/iharder/dnd/FileDrop.java index 74198967..cc3262e2 100644 --- a/src/net/iharder/dnd/FileDrop.java +++ b/src/net/iharder/dnd/FileDrop.java @@ -6,8 +6,6 @@ import java.io.IOException; import java.io.PrintStream; import java.io.Reader; -import java.util.logging.Level; -import java.util.logging.Logger; /** * This class makes it easy to drag and drop files from the operating @@ -43,6 +41,7 @@ *

*

Original author: Robert Harder, rharder@usa.net

*

2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.

+ *

2019-11-21 Kay Gürtzig -- Warnings eliminated by modernizing the code.

* * @author Robert Harder * @author rharder@users.sf.net @@ -314,9 +313,9 @@ public void drop( java.awt.dnd.DropTargetDropEvent evt ) log( out, "FileDrop: file list accepted." ); // Get a useful list - java.util.List fileList = (java.util.List) + java.util.List fileList = (java.util.List) tr.getTransferData(java.awt.datatransfer.DataFlavor.javaFileListFlavor); - java.util.Iterator iterator = fileList.iterator(); + //java.util.Iterator iterator = fileList.iterator(); // Convert list to array java.io.File[] filesTemp = new java.io.File[ fileList.size() ]; @@ -426,13 +425,13 @@ private static boolean supportsDnD() { boolean support = false; try - { Class arbitraryDndClass = Class.forName( "java.awt.dnd.DnDConstants" ); + { Class.forName( "java.awt.dnd.DnDConstants" ); support = true; } // end try catch( Exception e ) { support = false; } // end catch - supportsDnD = new Boolean( support ); + supportsDnD = Boolean.valueOf( support ); } // end if: first time through return supportsDnD.booleanValue(); } // end supportsDnD @@ -443,7 +442,7 @@ private static boolean supportsDnD() private static File[] createFileArray(BufferedReader bReader, PrintStream out) { try { - java.util.List list = new java.util.ArrayList(); + java.util.List list = new java.util.ArrayList(); java.lang.String line = null; while ((line = bReader.readLine()) != null) { try { @@ -625,7 +624,7 @@ public static void main( String[] args ) }); // end FileDrop.Listener frame.setBounds( 100, 100, 300, 400 ); - frame.setDefaultCloseOperation( frame.EXIT_ON_CLOSE ); + frame.setDefaultCloseOperation( javax.swing.JFrame.EXIT_ON_CLOSE ); //frame.show(); } // end main