-- Inequalities.mesa
-- Edited by Sweet, 21-Jan-81 21:40:58
DIRECTORY
Ascii,
Inline,
IODefs,
PressDefs,
PressUtilities,
Random,
String;
Inequalities: PROGRAM
IMPORTS Inline, IODefs, PressDefs, PressUtilities, Random, String =
BEGIN OPEN PressDefs;
pfdBody: PressFileDescriptor;
pfd: POINTER TO PressFileDescriptor = @pfdBody;
Mica: TYPE = CARDINAL;
MBox: TYPE = RECORD [x,y,w,h: Mica];
LineWidth: Mica ← 30;
CharHeight: Mica;
CharWidth: POINTER TO ARRAY CHARACTER OF Mica;
TextCharWidth: ARRAY CHARACTER OF Mica;
AnswerCharWidth: ARRAY CHARACTER OF Mica;
TextCharHeight: Mica;
AnswerCharHeight: Mica;
Minus: CHARACTER = Ascii.ControlX;
answers: BOOLEAN ← FALSE;
PointsToMicas: PROC [points: CARDINAL] RETURNS [Mica] =
{RETURN [Inline.LongDiv[Inline.LongMult[points, MicasPerInch],72]]};
maxValue: CARDINAL ← 10;
Prob: TYPE = RECORD [a,b: [0..16)];
HistSize: CARDINAL = 8;
history: ARRAY [0..HistSize) OF Prob ← ALL[[0,0]];
hp: CARDINAL ← 0;
Problem: PROC RETURNS [a,b: CARDINAL] =
BEGIN
trial: Prob;
DO
trial ← TrialProblem[];
FOR i: CARDINAL IN [0..HistSize) DO
IF history[i] = trial THEN EXIT;
REPEAT
FINISHED => GO TO ok;
ENDLOOP;
REPEAT
ok => NULL;
ENDLOOP;
history[hp] ← trial; hp ← (hp+1) MOD HistSize;
RETURN [trial.a, trial.b];
END;
TrialProblem: PROC RETURNS [trial: Prob] =
BEGIN
trial.a ← Random.InRange[0, maxValue];
DO
trial.b ← Random.InRange[0, maxValue];
IF trial.b # trial.a THEN EXIT;
ENDLOOP;
END;
StringWidth: PROC [s: STRING] RETURNS [l: Mica] =
BEGIN
l ← 0;
FOR i: CARDINAL IN [0..s.length) DO
l ← l + CharWidth[s[i]];
ENDLOOP;
END;
LineY: PROC [box: POINTER TO MBox, line, of: CARDINAL, lead: Mica ← 0]
RETURNS [Mica] =
BEGIN
h: Mica = CharHeight;
bottom: Mica = (box.h- of*h - (of-1)*lead)/2;
RETURN [box.y + bottom + (line-1)*(h+lead)];
END;
CenterLine: PROC [s: STRING, box: POINTER TO MBox, line, of: CARDINAL ← 1, lead: Mica ← 0] =
BEGIN
w: Mica = StringWidth[s];
y: Mica = LineY[box: box, line: line, of: of, lead: lead] + P3;
x: Mica = box.x + (box.w - w)/2;
PutText[pfd, s, x, y];
END;
RJLine: PROC [s: STRING, box: POINTER TO MBox, line, of: CARDINAL ← 1, lead: Mica ← 0] =
BEGIN
w: Mica = StringWidth[s];
y: Mica = LineY[box: box, line: line, of: of, lead: lead] + P3;
x: Mica = box.x + (box.w - w);
PutText[pfd, s, x, y];
END;
LJLine: PROC [s: STRING, box: POINTER TO MBox, line, of: CARDINAL ← 1, lead: Mica ← 0] =
BEGIN
y: Mica = LineY[box: box, line: line, of: of, lead: lead] + P3;
PutText[pfd, s, box.x, y];
END;
DrawBorder: PROC [box: POINTER TO MBox] =
BEGIN
PutRectangle[p: pfd,
xstart: box.x, ystart: box.y, xlen: box.w + LineWidth, ylen: LineWidth];
PutRectangle[p: pfd,
xstart: box.x, ystart: box.y, xlen: LineWidth, ylen: box.h];
PutRectangle[p: pfd,
xstart: box.x + box.w, ystart: box.y, xlen: LineWidth, ylen: box.h];
PutRectangle[p: pfd,
xstart: box.x, ystart: box.y + box.h,
xlen: box.w + LineWidth, ylen: LineWidth];
END;
FillOpInequality: PROC [x,y: Mica] RETURNS [Mica] =
BEGIN
ns: STRING ← [2];
box: MBox;
a,b: CARDINAL;
yBase: Mica = y - M38;
TextFont[];
[a, b] ← Problem[];
box ← [x: x, y: yBase, w: M38, h: M38];
CenterNum[a, @box];
box.x ← box.x + M38;
DrawBorder[@box];
IF answers THEN CenterLine[(IF a < b THEN "<"L ELSE ">"), @box];
box.x ← box.x + M38;
CenterNum[b, @box];
RETURN[y - M34];
END;
ChoiceInequality: PROC [x,y: Mica] RETURNS [Mica] =
BEGIN
ns: STRING ← [2];
box: MBox;
a,b: CARDINAL;
yBase: Mica = y - M38;
less: BOOLEAN = (Random.InRange[0,1] = 0);
upper: BOOLEAN;
TextFont[];
[a, b] ← Problem[];
upper ← less = (a < b);
box ← [x: x, y: yBase, w: M38, h: M38];
RJNum[a, @box];
box.x ← box.x + M38;
CenterLine[IF less THEN "<"L ELSE ">"L, @box];
box.x ← box.x + M38;
LJNum[b, @box];
box ← [x: x, y: yBase - M38, w: M38, h: M38];
RJNum[a, @box];
box.x ← box.x + M38;
CenterLine[IF less THEN ">"L ELSE "<"L, @box];
box.x ← box.x + M38;
LJNum[b, @box];
IF answers THEN {
box ← [x: x, y: (IF upper THEN yBase ELSE yBase-M38), w: 3*M38, h: M38];
DrawBorder[@box]};
RETURN[y - M34 - M14];
END;
FillNumberInequality: PROC [x,y: Mica] RETURNS [Mica] =
BEGIN
ns: STRING ← [2];
box: MBox;
a,b: CARDINAL;
less: BOOLEAN = (Random.InRange[0,1] = 0);
TextFont[];
[a, b] ← Problem[];
box ← [x: x + M38, y: y-M38, w: M38, h: M38];
DrawBorder[@box];
CenterNum[a, @box];
box.y ← box.y - M38 - P2;
DrawBorder[@box];
CenterNum[b, @box];
box.x ← x;
box.y ← box.y - M38 - P2;
PutRectangle[p: pfd,
xstart: box.x,
ystart: box.y,
xlen: M38,
ylen: P1];
IF answers THEN {
AnswerFont[];
CenterNum[(IF less THEN MIN[a,b] ELSE MAX[a,b]), @box];
TextFont[]};
box.x ← box.x + M38;
CenterLine[(IF less THEN "<"L ELSE ">"L), @box];
box.x ← box.x + M38;
PutRectangle[p: pfd,
xstart: box.x,
ystart: box.y,
xlen: M38,
ylen: P1];
IF answers THEN {
AnswerFont[];
CenterNum[(IF less THEN MAX[a,b] ELSE MIN[a,b]), @box];
TextFont[]};
RETURN[y - 2*M34 - P2];
END;
P1: Mica = PointsToMicas[1];
P2: Mica = PointsToMicas[2];
P3: Mica = PointsToMicas[3];
M1: Mica = MicasPerInch;
M12: Mica = MicasPerInch/2;
M14: Mica = MicasPerInch/4;
M18: Mica = MicasPerInch/8;
M34: Mica = (3*MicasPerInch)/4;
M38: Mica = (3*MicasPerInch)/8;
CenterNum: PROC [n: CARDINAL, box: POINTER TO MBox] =
BEGIN
w: Mica;
ns: STRING ← [2];
String.AppendDecimal[ns, n];
w ← StringWidth[ns];
PutText[pfd, ns, box.x + (box.w-w)/2, box.y + P3 + (box.h-CharHeight)/2];
END;
LJNum: PROC [n: CARDINAL, box: POINTER TO MBox] =
BEGIN
ns: STRING ← [2];
String.AppendDecimal[ns, n];
LJLine[ns, box];
END;
RJNum: PROC [n: CARDINAL, box: POINTER TO MBox] =
BEGIN
ns: STRING ← [2];
String.AppendDecimal[ns, n];
RJLine[ns, box];
END;
CenterChar: PROC [c: CHARACTER, box: POINTER TO MBox] =
BEGIN
w: Mica;
ns: STRING ← [2];
ns.length ← 1; ns[0] ← c;
w ← StringWidth[ns];
PutText[pfd, ns, box.x + (box.w-w)/2, box.y + P3 + (box.h-CharHeight)/2];
END;
TextFont: PROC =
BEGIN
SetFont[p: pfd, Name: "Helvetica", PointSize: 18, Face: 2];
CharHeight ← TextCharHeight;
CharWidth ← @TextCharWidth;
END;
AnswerFont: PROC =
BEGIN
SetFont[p: pfd, Name: "Helvetica", PointSize: 14, Face: 1];
CharHeight ← AnswerCharHeight;
CharWidth ← @AnswerCharWidth;
END;
DigestFonts: PROC =
BEGIN
[] ← PressUtilities.FindFontWidths[
family: "Helvetica"L,
points: 18,
weight: bold,
slope: regular,
widths: LOOPHOLE[@TextCharWidth]];
TextCharHeight ← PointsToMicas[18];
[] ← PressUtilities.FindFontWidths[
family: "Helvetica"L,
points: 14,
weight: medium,
slope: italic,
widths: LOOPHOLE[@AnswerCharWidth]];
AnswerCharHeight ← PointsToMicas[14];
END;
DoPage: PROC =
BEGIN
x, y, nexty: Mica;
x ← M1;
y ← 10*M1;
AnswerFont[];
PutText[pfd, "Complete the number sentences with < or >."L, M1, y];
y ← y - M14;
THROUGH [0..3) DO
x ← M1 + M14;
THROUGH [0..4) DO
nexty ← FillOpInequality[x, y];
x ← x + M1 + M18 + M12;
ENDLOOP;
y ← nexty;
ENDLOOP;
PutRectangle[p: pfd,
xstart: M1, ystart: y, xlen: 6*M1+M12, ylen: LineWidth];
y ← y - M14;
AnswerFont[];
PutText[pfd, "Complete the number sentences."L, M1, y];
y ← y - M14;
THROUGH [0..2) DO
x ← M1 + M14;
THROUGH [0..4) DO
nexty ← FillNumberInequality[x, y];
x ← x + M1 + M18 + M12;
ENDLOOP;
y ← nexty;
ENDLOOP;
PutRectangle[p: pfd,
xstart: M1, ystart: y, xlen: 6*M1+M12, ylen: LineWidth];
y ← y - M14;
AnswerFont[];
PutText[pfd, "Circle the true number sentences."L, M1, y];
y ← y - M14;
THROUGH [0..3) DO
x ← M1 + M14;
THROUGH [0..4) DO
nexty ← ChoiceInequality[x, y];
x ← x + M1 + M18 + M12;
ENDLOOP;
y ← nexty;
ENDLOOP;
WritePage[pfd];
END;
Driver: PROC =
BEGIN
state: Random.State;
BEGIN OPEN IODefs;
WriteString["max: "L];
maxValue ← ReadNumber[maxValue, 10];
WriteChar[CR];
END;
DigestFonts[];
InitPressFileDescriptor[pfd, "Math.drill"L];
answers ← FALSE;
Random.ReadState[@state];
THROUGH [0..3) DO DoPage[]; ENDLOOP;
ClosePressFile[pfd];
Random.WriteState[@state];
history ← ALL[[0,0]];
InitPressFileDescriptor[pfd, "Math.key"L];
answers ← TRUE;
THROUGH [0..3) DO DoPage[]; ENDLOOP;
ClosePressFile[pfd];
END;
Driver[];
END.