math-exercises 3.0.191 → 3.0.192
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/exercises/math/dataRepresentations/barChart/barChartInterpreting.d.ts +53 -0
- package/lib/exercises/math/dataRepresentations/barChart/barChartInterpreting.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/barChart/barChartInterpreting.js +543 -0
- package/lib/exercises/math/dataRepresentations/barChart/barChartReading.d.ts +94 -0
- package/lib/exercises/math/dataRepresentations/barChart/barChartReading.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/barChart/barChartReading.js +280 -0
- package/lib/exercises/math/dataRepresentations/barChart/index.d.ts +3 -0
- package/lib/exercises/math/dataRepresentations/barChart/index.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/barChart/index.js +2 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotInterpreting.d.ts +7 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotInterpreting.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotInterpreting.js +223 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotReading.d.ts +9 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotReading.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotReading.js +133 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotReadingPercentages.d.ts +11 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotReadingPercentages.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/boxPlotReadingPercentages.js +198 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/compareBoxPlot.d.ts +13 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/compareBoxPlot.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/compareBoxPlot.js +192 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/index.d.ts +5 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/index.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/boxPlot/index.js +4 -0
- package/lib/exercises/math/dataRepresentations/index.d.ts +4 -7
- package/lib/exercises/math/dataRepresentations/index.d.ts.map +1 -1
- package/lib/exercises/math/dataRepresentations/index.js +4 -11
- package/lib/exercises/math/dataRepresentations/tables/buildDoubleTableFromContext.d.ts +7 -0
- package/lib/exercises/math/dataRepresentations/tables/buildDoubleTableFromContext.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/tables/buildDoubleTableFromContext.js +222 -0
- package/lib/exercises/math/dataRepresentations/tables/fillDoubleTable.d.ts +7 -0
- package/lib/exercises/math/dataRepresentations/tables/fillDoubleTable.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/tables/fillDoubleTable.js +187 -0
- package/lib/exercises/math/dataRepresentations/tables/index.d.ts +4 -0
- package/lib/exercises/math/dataRepresentations/tables/index.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/tables/index.js +3 -0
- package/lib/exercises/math/dataRepresentations/tables/tableReading.d.ts +8 -0
- package/lib/exercises/math/dataRepresentations/tables/tableReading.d.ts.map +1 -0
- package/lib/exercises/math/dataRepresentations/tables/tableReading.js +109 -0
- package/lib/exercises/math/derivation/applications/findYearForDecreasingPopulation.d.ts +8 -0
- package/lib/exercises/math/derivation/applications/findYearForDecreasingPopulation.d.ts.map +1 -0
- package/lib/exercises/math/derivation/applications/findYearForDecreasingPopulation.js +145 -0
- package/lib/exercises/math/derivation/applications/index.d.ts +1 -0
- package/lib/exercises/math/derivation/applications/index.d.ts.map +1 -1
- package/lib/exercises/math/derivation/applications/index.js +1 -0
- package/lib/exercises/math/probaStat/conditional/fillTableConditionalProbabilitySituation.d.ts.map +1 -1
- package/lib/exercises/math/probaStat/conditional/fillTableConditionalProbabilitySituation.js +7 -2
- package/lib/exercises/math/probaStat/stats1var/marginalAndConditionalFrequency.d.ts.map +1 -1
- package/lib/exercises/math/probaStat/stats1var/marginalAndConditionalFrequency.js +131 -61
- package/lib/index.d.ts +32 -25
- package/lib/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Exercise } from "../../../../exercises/exercise.js";
|
|
2
|
+
type Identifiers = {
|
|
3
|
+
barChart: BarChart;
|
|
4
|
+
itemAsked: AskedItem;
|
|
5
|
+
questionStr: string;
|
|
6
|
+
answerStr: string;
|
|
7
|
+
displayType: string;
|
|
8
|
+
};
|
|
9
|
+
type AskedItem = {
|
|
10
|
+
type: "xForCategory" | "categoryForX";
|
|
11
|
+
isLess: boolean;
|
|
12
|
+
ordinal: number;
|
|
13
|
+
index: number;
|
|
14
|
+
};
|
|
15
|
+
type ColorStyle = {
|
|
16
|
+
type: "color";
|
|
17
|
+
color: string;
|
|
18
|
+
frStr: string;
|
|
19
|
+
};
|
|
20
|
+
type FillStyle = {
|
|
21
|
+
type: "fill";
|
|
22
|
+
fill: number;
|
|
23
|
+
frStr: string;
|
|
24
|
+
};
|
|
25
|
+
type CategoryProps = {
|
|
26
|
+
name: string;
|
|
27
|
+
frStr: string;
|
|
28
|
+
};
|
|
29
|
+
type CategoryStyle = ColorStyle | FillStyle;
|
|
30
|
+
type Category = {
|
|
31
|
+
props: CategoryProps;
|
|
32
|
+
style: CategoryStyle;
|
|
33
|
+
};
|
|
34
|
+
type BarProps = {
|
|
35
|
+
label: string;
|
|
36
|
+
frStr: string;
|
|
37
|
+
};
|
|
38
|
+
type Bar = {
|
|
39
|
+
props: BarProps;
|
|
40
|
+
data: number[];
|
|
41
|
+
};
|
|
42
|
+
type BarChart = {
|
|
43
|
+
description: string;
|
|
44
|
+
axisLabels: string[];
|
|
45
|
+
bars: Bar[];
|
|
46
|
+
categories: Category[];
|
|
47
|
+
};
|
|
48
|
+
type Options = {
|
|
49
|
+
displayType: string;
|
|
50
|
+
};
|
|
51
|
+
export declare const barChartInterpreting: Exercise<Identifiers, Options>;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=barChartInterpreting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barChartInterpreting.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/dataRepresentations/barChart/barChartInterpreting.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,QAAQ,EAKT,MAAM,6BAA6B,CAAC;AAYrC,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,cAAc,GAAG,cAAc,CAAC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE5C,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,GAAG,GAAG;IACT,KAAK,EAAE,QAAQ,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,UAAU,EAAE,QAAQ,EAAE,CAAC;CACxB,CAAC;AA4tBF,KAAK,OAAO,GAAG;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAsBF,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAe/D,CAAC"}
|
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
import { addValidProp, tryToAddWrongProp, GeneratorOptionTarget, GeneratorOptionType, } from "../../../../exercises/exercise.js";
|
|
2
|
+
import { random, randomMany } from "../../../../utils/alea/random.js";
|
|
3
|
+
import { randfloat } from "../../../../math/utils/random/randfloat.js";
|
|
4
|
+
import { blueMain, greenMain, orange, red } from "../../../../geogebra/colors.js";
|
|
5
|
+
import { coinFlip } from "../../../../utils/alea/coinFlip.js";
|
|
6
|
+
import { probaLawFlip } from "../../../../utils/alea/probaLawFlip.js";
|
|
7
|
+
import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQuestions.js";
|
|
8
|
+
import { randint } from "../../../../math/utils/random/randint.js";
|
|
9
|
+
import { GeogebraConstructor } from "../../../../geogebra/geogebraConstructor.js";
|
|
10
|
+
import { capitalize } from "../../../../utils/strings/capitalize.js";
|
|
11
|
+
import { defaultArrayedOptsWhereNeeded } from "../../../../exercises/utils/options/arrayedOptions.js";
|
|
12
|
+
class BarChartConstructor {
|
|
13
|
+
static stylesPools = {
|
|
14
|
+
color: [
|
|
15
|
+
{
|
|
16
|
+
type: "color",
|
|
17
|
+
color: blueMain,
|
|
18
|
+
frStr: "bleu",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: "color",
|
|
22
|
+
color: orange,
|
|
23
|
+
frStr: "orange",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "color",
|
|
27
|
+
color: red,
|
|
28
|
+
frStr: "rouge",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: "color",
|
|
32
|
+
color: greenMain,
|
|
33
|
+
frStr: "vert",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
fill: [
|
|
37
|
+
{
|
|
38
|
+
type: "fill",
|
|
39
|
+
fill: 1,
|
|
40
|
+
frStr: "hachures simples",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: "fill",
|
|
44
|
+
fill: 2,
|
|
45
|
+
frStr: "hachures croisées",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "fill",
|
|
49
|
+
fill: 5,
|
|
50
|
+
frStr: "nid d'abeille",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: "fill",
|
|
54
|
+
fill: 4,
|
|
55
|
+
frStr: "petits points",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: "fill",
|
|
59
|
+
fill: 3,
|
|
60
|
+
frStr: "échiquier",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
static randomFromSkeleton(skeleton, nbBars, nbCateg, styleType) {
|
|
65
|
+
const categoryIndexes = randomMany([...Array(skeleton.categoryProps.length).keys()], nbCateg);
|
|
66
|
+
const dictIsUsingCategory = Object.fromEntries(categoryIndexes.map((i) => [i, true]));
|
|
67
|
+
const bars = this.createRandomBars(nbBars, dictIsUsingCategory, skeleton.barProps, skeleton.referenceData, skeleton.evoRanges).toSorted((bar1, bar2) => bar1.props.label.localeCompare(bar2.props.label));
|
|
68
|
+
const categories = this.createRandomCategories(dictIsUsingCategory, skeleton.categoryProps, styleType);
|
|
69
|
+
return {
|
|
70
|
+
description: skeleton.description,
|
|
71
|
+
axisLabels: skeleton.axisLabels,
|
|
72
|
+
bars,
|
|
73
|
+
categories,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
static createRandomBars(nbBars, dictIsUsingCategory, barPropsPool, referenceDataIn, evoRangesIn) {
|
|
77
|
+
const barProps = randomMany(barPropsPool, nbBars);
|
|
78
|
+
function createRandomDataByPerturbatingData(data, evoRanges) {
|
|
79
|
+
return data.map((nb, i) => {
|
|
80
|
+
const evoRange = evoRanges[i];
|
|
81
|
+
return nb * randfloat(evoRange.min, evoRange.max);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const evoRanges = evoRangesIn.filter((_, categIndex) => dictIsUsingCategory[categIndex]);
|
|
85
|
+
let referenceData = referenceDataIn.filter((_, categIndex) => dictIsUsingCategory[categIndex]);
|
|
86
|
+
const datas = [];
|
|
87
|
+
for (let i = 0; i < nbBars; i++) {
|
|
88
|
+
const data = createRandomDataByPerturbatingData(referenceData, evoRanges);
|
|
89
|
+
datas.push(data);
|
|
90
|
+
referenceData = data;
|
|
91
|
+
}
|
|
92
|
+
return [...Array(nbBars).keys()].map((i) => {
|
|
93
|
+
return {
|
|
94
|
+
props: barProps[i],
|
|
95
|
+
data: datas[i],
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
static createRandomCategories(dictIsUsingCategory, categoryPropsPool, styleType) {
|
|
100
|
+
const nbCategUsed = Object.keys(dictIsUsingCategory).length;
|
|
101
|
+
const styles = this.stylesPools[styleType].slice(0, nbCategUsed);
|
|
102
|
+
return categoryPropsPool
|
|
103
|
+
.filter((_, i) => dictIsUsingCategory[i])
|
|
104
|
+
.map((props, i) => {
|
|
105
|
+
const style = styles[i];
|
|
106
|
+
return {
|
|
107
|
+
props,
|
|
108
|
+
style,
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const frenchOrdinals = [``, "deuxième", "troisième", "quatrième"];
|
|
114
|
+
const arrayOfBarChartSkeleton = [
|
|
115
|
+
{
|
|
116
|
+
description: `Le diagramme en barres ci-dessous donne la production d'électricité, en TWh (téraWatt-heure) selon son origine.`,
|
|
117
|
+
questionXForCategFunc(categName, isLess, ordinal) {
|
|
118
|
+
return `Quelle était l'année où la production d'électricité d'origine ${categName.toLocaleLowerCase()} était
|
|
119
|
+
la ${ordinal > 0 ? `${frenchOrdinals[ordinal]} la` : ``} ${isLess ? `moins` : `plus`} importante de toutes ces années ?`;
|
|
120
|
+
},
|
|
121
|
+
answerXForCategFunc(categName, isLess, ordinal) {
|
|
122
|
+
return `l'année où la production d'électricité d'origine ${categName.toLocaleLowerCase()} était
|
|
123
|
+
la ${ordinal > 0 ? `${frenchOrdinals[ordinal]} la` : ``} ${isLess ? `moins` : `plus`} importante de toutes ces années`;
|
|
124
|
+
},
|
|
125
|
+
questionCategForXFunc(barLabel, isLess, ordinal) {
|
|
126
|
+
return `Quelle était la ${ordinal > 0 ? `${frenchOrdinals[ordinal]}` : ``} ${isLess ? `moins` : `plus`} importante origine de production d'électricité pour l'année $${barLabel}$ ?`;
|
|
127
|
+
},
|
|
128
|
+
answerCategForXFunc(barLabel, isLess, ordinal) {
|
|
129
|
+
return `la ${ordinal > 0 ? `${frenchOrdinals[ordinal]} la` : ``} ${isLess ? `moins` : `plus`} importante origine de production d'électricité pour l'année $${barLabel}$`;
|
|
130
|
+
},
|
|
131
|
+
axisLabels: ["Année", "Production d'électricité (en TWh)"],
|
|
132
|
+
categoryProps: (() => {
|
|
133
|
+
const categoryNames = [
|
|
134
|
+
"Nucléaire",
|
|
135
|
+
"Thermique",
|
|
136
|
+
"Hydraulique",
|
|
137
|
+
"Solaire",
|
|
138
|
+
"Éolienne",
|
|
139
|
+
];
|
|
140
|
+
return categoryNames.map((name) => {
|
|
141
|
+
return {
|
|
142
|
+
name,
|
|
143
|
+
frStr: `la production d'électricité d'origine ${name.toLocaleLowerCase()}`,
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
})(),
|
|
147
|
+
barProps: (() => {
|
|
148
|
+
const labels = [...Array(30).keys()].map((i) => `${1995 + i}`);
|
|
149
|
+
return labels.map((label) => {
|
|
150
|
+
return {
|
|
151
|
+
label,
|
|
152
|
+
frStr: `l'année $${label}$`,
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
})(),
|
|
156
|
+
referenceData: [500, 450, 400, 350, 300],
|
|
157
|
+
evoRanges: [
|
|
158
|
+
{ min: 0.95, max: 1.05 },
|
|
159
|
+
{ min: 0.9, max: 1.1 },
|
|
160
|
+
{ min: 0.8, max: 1.2 },
|
|
161
|
+
{ min: 0.7, max: 1.3 },
|
|
162
|
+
{ min: 0.7, max: 1.3 },
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
const getInstruction = (identifiers) => {
|
|
167
|
+
const { barChart, questionStr } = identifiers;
|
|
168
|
+
return `${barChart.description}
|
|
169
|
+
|
|
170
|
+
${questionStr}
|
|
171
|
+
|
|
172
|
+
Légende :
|
|
173
|
+
|
|
174
|
+
${barChart.categories
|
|
175
|
+
.map((category) => {
|
|
176
|
+
return `${category.props.name} (${category.style.frStr})
|
|
177
|
+
|
|
178
|
+
`;
|
|
179
|
+
})
|
|
180
|
+
.join("")}
|
|
181
|
+
`;
|
|
182
|
+
};
|
|
183
|
+
const getAnswerCategory = (barChart, itemAsked) => {
|
|
184
|
+
const bar = barChart.bars[itemAsked.index];
|
|
185
|
+
const categIndex = bar.data
|
|
186
|
+
.map((data, i) => {
|
|
187
|
+
return { data: data, categIndex: i };
|
|
188
|
+
})
|
|
189
|
+
.toSorted((obj1, obj2) => (itemAsked.isLess ? +1 : -1) * (obj1.data - obj2.data))[itemAsked.ordinal].categIndex;
|
|
190
|
+
return barChart.categories[categIndex];
|
|
191
|
+
};
|
|
192
|
+
const getAnswerBar = (barChart, itemAsked) => {
|
|
193
|
+
const categIndex = itemAsked.index;
|
|
194
|
+
const barIndex = barChart.bars
|
|
195
|
+
.map((bar) => bar.data[categIndex])
|
|
196
|
+
.map((data, i) => {
|
|
197
|
+
return { data: data, barIndex: i };
|
|
198
|
+
})
|
|
199
|
+
.toSorted((obj1, obj2) => (itemAsked.isLess ? +1 : -1) * (obj1.data - obj2.data))[itemAsked.ordinal].barIndex;
|
|
200
|
+
return barChart.bars[barIndex];
|
|
201
|
+
};
|
|
202
|
+
const getAnswer = (identifiers) => {
|
|
203
|
+
const { barChart, itemAsked } = identifiers;
|
|
204
|
+
switch (itemAsked.type) {
|
|
205
|
+
case "categoryForX":
|
|
206
|
+
return getAnswerCategory(barChart, itemAsked).props.name;
|
|
207
|
+
case "xForCategory":
|
|
208
|
+
return getAnswerBar(barChart, itemAsked).props.label;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
const getPropositions = (_, { answer, ...identifiers }) => {
|
|
212
|
+
const { barChart, itemAsked } = identifiers;
|
|
213
|
+
const propositions = [];
|
|
214
|
+
switch (itemAsked.type) {
|
|
215
|
+
case "categoryForX":
|
|
216
|
+
{
|
|
217
|
+
barChart.categories.forEach((categ) => {
|
|
218
|
+
if (categ.props.name === answer) {
|
|
219
|
+
addValidProp(propositions, categ.props.name, "raw");
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
tryToAddWrongProp(propositions, categ.props.name, "raw");
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
case "xForCategory":
|
|
228
|
+
{
|
|
229
|
+
barChart.bars.forEach((bar) => {
|
|
230
|
+
if (bar.props.label === answer) {
|
|
231
|
+
addValidProp(propositions, bar.props.label, "raw");
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
tryToAddWrongProp(propositions, bar.props.label, "raw");
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
return propositions;
|
|
241
|
+
};
|
|
242
|
+
const getHint = (identifiers) => {
|
|
243
|
+
const { barChart, itemAsked } = identifiers;
|
|
244
|
+
switch (itemAsked.type) {
|
|
245
|
+
case "categoryForX": {
|
|
246
|
+
const bar = barChart.bars[itemAsked.index];
|
|
247
|
+
return `Concentre-toi sur ${bar.props.frStr}.`;
|
|
248
|
+
}
|
|
249
|
+
case "xForCategory": {
|
|
250
|
+
const category = barChart.categories[itemAsked.index];
|
|
251
|
+
return `Concentre-toi sur les barres ${category.style.type === "color"
|
|
252
|
+
? `en ${category.style.frStr}`
|
|
253
|
+
: `en style ${category.style.frStr}`}.`;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
const getCorrection = (identifiers) => {
|
|
258
|
+
const { barChart, itemAsked, answerStr } = identifiers;
|
|
259
|
+
switch (itemAsked.type) {
|
|
260
|
+
case "categoryForX": {
|
|
261
|
+
const answerCategory = getAnswerCategory(barChart, itemAsked);
|
|
262
|
+
return `On cherche ${answerStr}.
|
|
263
|
+
${capitalize(answerStr)} est ${answerCategory.props.frStr}.`;
|
|
264
|
+
}
|
|
265
|
+
case "xForCategory": {
|
|
266
|
+
const category = barChart.categories[itemAsked.index];
|
|
267
|
+
const answerBar = getAnswerBar(barChart, itemAsked);
|
|
268
|
+
return `Comme ${category.props.frStr} est indiquée ${category.style.type === "color"
|
|
269
|
+
? `en ${category.style.frStr}`
|
|
270
|
+
: `en style ${category.style.frStr}`} sur le diagramme , on cherche ${answerStr}.
|
|
271
|
+
${capitalize(answerStr)} est ${answerBar.props.frStr}.`;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
const getGGBOptionsHorizMulti = (identifiers) => {
|
|
276
|
+
const { barChart } = identifiers;
|
|
277
|
+
const nbTotalBar = barChart.bars.length;
|
|
278
|
+
const nbTotalCateg = barChart.categories.length;
|
|
279
|
+
const yMax = Math.max(...barChart.bars.flatMap((bar) => bar.data));
|
|
280
|
+
const xMax = 3.0 * yMax;
|
|
281
|
+
function getXRangeForCategory(barIndex, categIndex) {
|
|
282
|
+
const xRangeBar = {
|
|
283
|
+
min: (xMax * (2 * barIndex + 1)) / (2 * nbTotalBar + 2),
|
|
284
|
+
max: (xMax * (2 * barIndex + 2)) / (2 * nbTotalBar + 2),
|
|
285
|
+
};
|
|
286
|
+
const progressMin = categIndex / (nbTotalCateg + 1);
|
|
287
|
+
const progressMax = (categIndex + 1) / (nbTotalCateg + 1);
|
|
288
|
+
return {
|
|
289
|
+
min: xRangeBar.min + progressMin * (xRangeBar.max - xRangeBar.min),
|
|
290
|
+
max: xRangeBar.min + progressMax * (xRangeBar.max - xRangeBar.min),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
function createBarChartCommandsForCategory(barChart, categIndex) {
|
|
294
|
+
const arrayXRange = barChart.bars.map((_, barIndex) => getXRangeForCategory(barIndex, categIndex));
|
|
295
|
+
const arrayX = arrayXRange.map((xRange) => xRange.min);
|
|
296
|
+
const arrayY = barChart.bars.map((bar) => bar.data[categIndex]);
|
|
297
|
+
const categ = barChart.categories[categIndex];
|
|
298
|
+
const style = categ.style;
|
|
299
|
+
const B = `B_${categIndex}`;
|
|
300
|
+
const barChartCommand = [
|
|
301
|
+
`${B} = BarChart({${arrayX.join(",")}}, {${arrayY.join(",")}}, ${xMax / ((2 * nbTotalBar + 2) * (nbTotalCateg + 1))})`,
|
|
302
|
+
`ShowLabel(${B},false)`,
|
|
303
|
+
style.type === "color"
|
|
304
|
+
? `SetColor(${B}, "${barChart.categories[categIndex].style.color}")`
|
|
305
|
+
: `SetDecoration(${B}, ${barChart.categories[categIndex].style.fill})`,
|
|
306
|
+
];
|
|
307
|
+
return barChartCommand;
|
|
308
|
+
}
|
|
309
|
+
const commands = [
|
|
310
|
+
//offsetted barCharts
|
|
311
|
+
...barChart.categories.flatMap((_, categIndex) => createBarChartCommandsForCategory(barChart, categIndex)),
|
|
312
|
+
//bar labels
|
|
313
|
+
...barChart.bars.map((bar, barIndex) => `Text("\\footnotesize ${bar.props.label}", (${(xMax * (2 * barIndex + 1)) / (2 * nbTotalBar + 2)}, ${-yMax / 500}), true, true, 0, -1)`),
|
|
314
|
+
];
|
|
315
|
+
const ggb = new GeogebraConstructor({
|
|
316
|
+
commands,
|
|
317
|
+
gridDistance: [xMax, yMax],
|
|
318
|
+
fontSize: 16,
|
|
319
|
+
lockedAxesRatio: 4 / 3,
|
|
320
|
+
xAxis: {
|
|
321
|
+
hideNumbers: true,
|
|
322
|
+
steps: 10 * xMax,
|
|
323
|
+
showPositive: true,
|
|
324
|
+
label: barChart.axisLabels[0],
|
|
325
|
+
},
|
|
326
|
+
yAxis: {
|
|
327
|
+
showPositive: true,
|
|
328
|
+
label: barChart.axisLabels[1],
|
|
329
|
+
// steps: 100,
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
return ggb.getOptions({
|
|
333
|
+
coords: ggb.getAdaptedCoords({
|
|
334
|
+
xMin: 0,
|
|
335
|
+
xMax: xMax,
|
|
336
|
+
yMin: 0,
|
|
337
|
+
yMax: yMax,
|
|
338
|
+
}),
|
|
339
|
+
});
|
|
340
|
+
};
|
|
341
|
+
const getGGBOptionsVertStacked = (identifiers) => {
|
|
342
|
+
const { barChart } = identifiers;
|
|
343
|
+
const nbTotalBar = barChart.bars.length;
|
|
344
|
+
const arrayOfBarHeights = barChart.bars.map((bar) => bar.data.reduce((acc, data) => acc + data, 0));
|
|
345
|
+
const yMax = Math.max(...arrayOfBarHeights);
|
|
346
|
+
const xMax = 3.0 * yMax;
|
|
347
|
+
const xPadding = 0.1 * xMax;
|
|
348
|
+
const xMargin = xPadding;
|
|
349
|
+
const barWidth = (xMax - 2 * xMargin - (nbTotalBar - 1) * xPadding) / nbTotalBar;
|
|
350
|
+
function getXRangeForBarIndex(barIndex) {
|
|
351
|
+
const xMin = xMargin + barIndex * (xPadding + barWidth);
|
|
352
|
+
return {
|
|
353
|
+
min: xMin,
|
|
354
|
+
max: xMin + barWidth,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function getYRangeForCategory(barIndex, categIndex, isTopToBottom = true) {
|
|
358
|
+
const slice = barChart.bars[barIndex].data.slice(0, categIndex);
|
|
359
|
+
const yMinForCateg = slice.reduce((acc, data) => acc + data, 0);
|
|
360
|
+
const yMaxForCateg = yMinForCateg + barChart.bars[barIndex].data[categIndex];
|
|
361
|
+
return {
|
|
362
|
+
min: isTopToBottom
|
|
363
|
+
? arrayOfBarHeights[barIndex] - yMinForCateg
|
|
364
|
+
: yMinForCateg,
|
|
365
|
+
max: isTopToBottom
|
|
366
|
+
? arrayOfBarHeights[barIndex] - yMaxForCateg
|
|
367
|
+
: yMaxForCateg,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function createCommandsForBar(barChart, barIndex) {
|
|
371
|
+
//const bar = barChart.bars[barIndex];
|
|
372
|
+
const commands = barChart.categories.flatMap((categ, categIndex) => {
|
|
373
|
+
const xRange = getXRangeForBarIndex(barIndex);
|
|
374
|
+
const yRange = getYRangeForCategory(barIndex, categIndex, true);
|
|
375
|
+
const style = categ.style;
|
|
376
|
+
const B = `B_{${barIndex}${categIndex}}`;
|
|
377
|
+
const barChartCommand = [
|
|
378
|
+
`${B} = Polygon((${xRange.min}, ${yRange.min}), (${xRange.min}, ${yRange.max}),(${xRange.max}, ${yRange.max}),(${xRange.max}, ${yRange.min}))`,
|
|
379
|
+
`ShowLabel(${B},false)`,
|
|
380
|
+
style.type === "color"
|
|
381
|
+
? `SetColor(${B}, "${categ.style.color}")`
|
|
382
|
+
: `SetDecoration(${B}, ${categ.style.fill})`,
|
|
383
|
+
];
|
|
384
|
+
return barChartCommand;
|
|
385
|
+
});
|
|
386
|
+
return commands;
|
|
387
|
+
}
|
|
388
|
+
const commands = [
|
|
389
|
+
//stacked bars
|
|
390
|
+
...barChart.bars.flatMap((_, barIndex) => createCommandsForBar(barChart, barIndex)),
|
|
391
|
+
//bar labels
|
|
392
|
+
...barChart.bars.map((bar, barIndex) => `Text("\\footnotesize ${bar.props.label}", (${getXRangeForBarIndex(barIndex).min}, ${-yMax / 500}), true, true, 0, -1)`),
|
|
393
|
+
];
|
|
394
|
+
const ggb = new GeogebraConstructor({
|
|
395
|
+
commands,
|
|
396
|
+
gridDistance: [xMax, yMax],
|
|
397
|
+
fontSize: 16,
|
|
398
|
+
lockedAxesRatio: 4 / 3,
|
|
399
|
+
xAxis: {
|
|
400
|
+
hideNumbers: true,
|
|
401
|
+
steps: 10 * xMax,
|
|
402
|
+
showPositive: true,
|
|
403
|
+
label: barChart.axisLabels[0],
|
|
404
|
+
},
|
|
405
|
+
yAxis: {
|
|
406
|
+
showPositive: true,
|
|
407
|
+
label: barChart.axisLabels[1],
|
|
408
|
+
// steps: 100,
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
return ggb.getOptions({
|
|
412
|
+
coords: ggb.getAdaptedCoords({
|
|
413
|
+
xMin: 0,
|
|
414
|
+
xMax: xMax,
|
|
415
|
+
yMin: 0,
|
|
416
|
+
yMax: yMax,
|
|
417
|
+
}),
|
|
418
|
+
});
|
|
419
|
+
};
|
|
420
|
+
const getGGBOptions = (identifiers, opts) => {
|
|
421
|
+
const { displayType } = identifiers;
|
|
422
|
+
switch (displayType) {
|
|
423
|
+
case "empilements":
|
|
424
|
+
return getGGBOptionsVertStacked(identifiers, opts);
|
|
425
|
+
default:
|
|
426
|
+
case "faisceaux":
|
|
427
|
+
return getGGBOptionsHorizMulti(identifiers, opts);
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
const getBarChartInterpretingQuestion = (optsIn) => {
|
|
431
|
+
const arrayedOpts = defaultArrayedOptsWhereNeeded(optsIn, arrayedOptsDefault);
|
|
432
|
+
const opts = {
|
|
433
|
+
displayType: random(arrayedOpts.displayType),
|
|
434
|
+
};
|
|
435
|
+
const styleType = "color";
|
|
436
|
+
const displayType = opts.displayType;
|
|
437
|
+
let nbBars;
|
|
438
|
+
let nbCateg;
|
|
439
|
+
switch (displayType) {
|
|
440
|
+
case "empilements":
|
|
441
|
+
{
|
|
442
|
+
nbBars = 5;
|
|
443
|
+
nbCateg = 3;
|
|
444
|
+
}
|
|
445
|
+
break;
|
|
446
|
+
default:
|
|
447
|
+
case "faisceaux":
|
|
448
|
+
{
|
|
449
|
+
nbBars = 3;
|
|
450
|
+
nbCateg = 3;
|
|
451
|
+
}
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
const barChartSkeleton = random(arrayOfBarChartSkeleton);
|
|
455
|
+
const barChart = BarChartConstructor.randomFromSkeleton(barChartSkeleton, nbBars, nbCateg, styleType);
|
|
456
|
+
const itemAsked = random([
|
|
457
|
+
// {
|
|
458
|
+
// type: "xForCategory",
|
|
459
|
+
// isLess: coinFlip(),
|
|
460
|
+
// ordinal: probaLawFlip([
|
|
461
|
+
// [0, 0.7],
|
|
462
|
+
// [1, 0.3],
|
|
463
|
+
// ]),
|
|
464
|
+
// index: randint(0, nbCateg),
|
|
465
|
+
// },
|
|
466
|
+
{
|
|
467
|
+
type: "categoryForX",
|
|
468
|
+
isLess: coinFlip(),
|
|
469
|
+
ordinal: probaLawFlip([
|
|
470
|
+
[0, 0.7],
|
|
471
|
+
[1, 0.3],
|
|
472
|
+
]),
|
|
473
|
+
index: randint(0, nbBars),
|
|
474
|
+
},
|
|
475
|
+
]);
|
|
476
|
+
function questionStrForItemAsked(itemAsked) {
|
|
477
|
+
switch (itemAsked.type) {
|
|
478
|
+
case "xForCategory":
|
|
479
|
+
return barChartSkeleton.questionXForCategFunc(barChart.categories[itemAsked.index].props.name, itemAsked.isLess, itemAsked.ordinal);
|
|
480
|
+
case "categoryForX":
|
|
481
|
+
return barChartSkeleton.questionCategForXFunc(barChart.bars[itemAsked.index].props.label, itemAsked.isLess, itemAsked.ordinal);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
const questionStr = questionStrForItemAsked(itemAsked);
|
|
485
|
+
function answerStrForItemAsked(itemAsked) {
|
|
486
|
+
switch (itemAsked.type) {
|
|
487
|
+
case "xForCategory":
|
|
488
|
+
return barChartSkeleton.answerXForCategFunc(barChart.categories[itemAsked.index].props.name, itemAsked.isLess, itemAsked.ordinal);
|
|
489
|
+
case "categoryForX":
|
|
490
|
+
return barChartSkeleton.answerCategForXFunc(barChart.bars[itemAsked.index].props.label, itemAsked.isLess, itemAsked.ordinal);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
const answerStr = answerStrForItemAsked(itemAsked);
|
|
494
|
+
return getQuestionFromIdentifiers({
|
|
495
|
+
barChart,
|
|
496
|
+
itemAsked,
|
|
497
|
+
questionStr,
|
|
498
|
+
answerStr,
|
|
499
|
+
displayType,
|
|
500
|
+
}, opts);
|
|
501
|
+
};
|
|
502
|
+
const getQuestionFromIdentifiers = (identifiers, opts) => {
|
|
503
|
+
const question = {
|
|
504
|
+
answer: getAnswer(identifiers),
|
|
505
|
+
instruction: getInstruction(identifiers),
|
|
506
|
+
keys: [],
|
|
507
|
+
answerFormat: "tex",
|
|
508
|
+
identifiers,
|
|
509
|
+
hint: getHint(identifiers),
|
|
510
|
+
correction: getCorrection(identifiers),
|
|
511
|
+
ggbOptions: getGGBOptions(identifiers),
|
|
512
|
+
options: opts,
|
|
513
|
+
};
|
|
514
|
+
return question;
|
|
515
|
+
};
|
|
516
|
+
const arrayedOptsDefault = {
|
|
517
|
+
displayType: ["faisceaux", "empilements"],
|
|
518
|
+
};
|
|
519
|
+
const options = [
|
|
520
|
+
{
|
|
521
|
+
id: "displayType",
|
|
522
|
+
label: "Type de diagramme",
|
|
523
|
+
target: GeneratorOptionTarget.generation,
|
|
524
|
+
type: GeneratorOptionType.multiselect,
|
|
525
|
+
values: ["faisceaux", "empilements"],
|
|
526
|
+
defaultValue: arrayedOptsDefault.displayType,
|
|
527
|
+
},
|
|
528
|
+
];
|
|
529
|
+
export const barChartInterpreting = {
|
|
530
|
+
id: "barChartInterpreting",
|
|
531
|
+
label: "Interpréter un diagramme en bâtons",
|
|
532
|
+
isSingleStep: true,
|
|
533
|
+
generator: (nb, opts) => getDistinctQuestions(() => getBarChartInterpretingQuestion(opts), nb),
|
|
534
|
+
options,
|
|
535
|
+
qcmTimer: 60,
|
|
536
|
+
freeTimer: 60,
|
|
537
|
+
getPropositions,
|
|
538
|
+
hasHintAndCorrection: true,
|
|
539
|
+
subject: "Mathématiques",
|
|
540
|
+
getQuestionFromIdentifiers,
|
|
541
|
+
hasGeogebra: true,
|
|
542
|
+
answerType: "QCU",
|
|
543
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Exercise } from "../../../../exercises/exercise.js";
|
|
2
|
+
type Identifiers = {
|
|
3
|
+
labels: string[];
|
|
4
|
+
data: number[];
|
|
5
|
+
itemAsked: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const barChartReading: Exercise<Identifiers>;
|
|
8
|
+
export {};
|
|
9
|
+
/***Final version */
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* const newspapers = [
|
|
13
|
+
{ name: "Le Figaro", sales: 320000 },
|
|
14
|
+
{ name: "Les Échos", sales: 130000 },
|
|
15
|
+
{ name: "La Croix", sales: 90000 },
|
|
16
|
+
{ name: "L'Équipe", sales: 210000 },
|
|
17
|
+
{ name: "Le Monde", sales: 330000 },
|
|
18
|
+
{ name: "Le Parisien", sales: 270000 },
|
|
19
|
+
{ name: "Libération", sales: 70000 },
|
|
20
|
+
{ name: "L'Humanité", sales: 30000 },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const width = 600,
|
|
24
|
+
height = 400,
|
|
25
|
+
margin = { top: 20, right: 30, bottom: 100, left: 60 };
|
|
26
|
+
const d3n = new D3Node();
|
|
27
|
+
const d3 = d3n.d3;
|
|
28
|
+
|
|
29
|
+
const svg = d3n.createSVG(width, height);
|
|
30
|
+
|
|
31
|
+
const xScale = d3
|
|
32
|
+
.scaleBand()
|
|
33
|
+
.domain(newspapers.map((d) => d.name))
|
|
34
|
+
.range([margin.left, width - margin.right])
|
|
35
|
+
.padding(0.1);
|
|
36
|
+
|
|
37
|
+
const yScale = d3
|
|
38
|
+
.scaleLinear()
|
|
39
|
+
.domain([0, d3.max(newspapers, (d: any) => d.sales)])
|
|
40
|
+
.nice()
|
|
41
|
+
.range([height - margin.bottom, margin.top]);
|
|
42
|
+
|
|
43
|
+
svg
|
|
44
|
+
.append("g")
|
|
45
|
+
.attr("transform", `translate(0,${height - margin.bottom})`)
|
|
46
|
+
.call(d3.axisBottom(xScale).tickSize(0))
|
|
47
|
+
.selectAll("text")
|
|
48
|
+
.style("text-anchor", "end")
|
|
49
|
+
.attr("transform", "rotate(-30)");
|
|
50
|
+
|
|
51
|
+
svg
|
|
52
|
+
.append("g")
|
|
53
|
+
.attr("transform", `translate(${margin.left},0)`)
|
|
54
|
+
.call(
|
|
55
|
+
d3
|
|
56
|
+
.axisLeft(yScale)
|
|
57
|
+
.ticks(5)
|
|
58
|
+
.tickFormat((d: any) =>
|
|
59
|
+
d.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " "),
|
|
60
|
+
),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
svg
|
|
64
|
+
.append("text")
|
|
65
|
+
.attr("x", margin.left)
|
|
66
|
+
.attr("y", margin.top)
|
|
67
|
+
.attr("text-anchor", "start")
|
|
68
|
+
.style("font-size", "14px")
|
|
69
|
+
.style("font-weight", "bold")
|
|
70
|
+
.text("Nombre d'exemplaires vendus");
|
|
71
|
+
|
|
72
|
+
svg
|
|
73
|
+
.selectAll(".bar")
|
|
74
|
+
.data(newspapers)
|
|
75
|
+
.enter()
|
|
76
|
+
.append("rect")
|
|
77
|
+
.attr("class", "bar")
|
|
78
|
+
.attr("x", (d: any) => xScale(d.name))
|
|
79
|
+
.attr("y", (d: any) => yScale(d.sales))
|
|
80
|
+
.attr("width", xScale.bandwidth())
|
|
81
|
+
.attr("height", (d: any) => height - margin.bottom - yScale(d.sales))
|
|
82
|
+
.attr("fill", "steelblue");
|
|
83
|
+
|
|
84
|
+
const svgString = d3n.svgString();
|
|
85
|
+
return `BBteeeezfst :
|
|
86
|
+
|
|
87
|
+
ofzie
|
|
88
|
+
should read this
|
|
89
|
+
${svgString}
|
|
90
|
+
should read this
|
|
91
|
+
zef
|
|
92
|
+
`;
|
|
93
|
+
*/
|
|
94
|
+
//# sourceMappingURL=barChartReading.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barChartReading.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/dataRepresentations/barChart/barChartReading.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAiBT,MAAM,6BAA6B,CAAC;AAOrC,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAwIF,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,WAAW,CAgBjD,CAAC;;AAgFF,oBAAoB;AACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG"}
|