Skip to content

Commit 858936f

Browse files
committed
Add in xlsx file support edit qtype, fraction, fine, penalty, fix some issue with processed count questions
1 parent 5c711ee commit 858936f

File tree

1 file changed

+106
-66
lines changed

1 file changed

+106
-66
lines changed

format.php

Lines changed: 106 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,21 @@ public function provide_import()
2020
{
2121
return true;
2222

23-
}
23+
}//end provide_import()
2424

2525

2626
public function provide_export()
2727
{
2828
return true;
2929

30-
}
30+
}//end provide_export()
3131

3232

3333
public function mime_type()
3434
{
3535
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
3636

37-
}
37+
}//end mime_type()
3838

3939

4040
public function validate_file(stored_file $file): string
@@ -45,143 +45,175 @@ public function validate_file(stored_file $file): string
4545

4646
return '';
4747

48-
}
48+
}//end validate_file()
49+
4950

5051
public function readquestions($data)
5152
{
52-
$allQuestions = [];
53+
$qa = [];
5354
foreach ($data['sheets'] as $sheetIndex => $sheetData) {
54-
$sheet = $sheetData['rows'];
55-
$images = $sheetData['images'] ?? [];
56-
$name = $this->bottom_value('_name', $sheet);
57-
$time = $this->bottom_value('_time', $sheet);
58-
$attempts = $this->bottom_value('_attempts', $sheet);
59-
$password = $this->bottom_value('_password', $sheet);
60-
$fine = $this->bottom_value('_fine', $sheet);
61-
$keys = $this->process_data($sheet);
62-
$countQuestions = max(array_map(fn ($item) => count($item), $sheet));
63-
64-
for($i = 0; $i < $countQuestions; $i++) {
65-
$questiontext = $this->bottom_value('_text', $sheet);
55+
$sheet = $sheetData['rows'];
56+
$images = ($sheetData['images'] ?? []);
57+
$name = $this->bottom_value('_name', $sheet, 'Name not found');
58+
$fine = $this->abs_val($this->bottom_value('_fine', $sheet, '0.1'));
59+
$penalty = $this->abs_val($this->bottom_value('_penalty', $sheet, '0.333'));
60+
$fraction = $this->abs_val($this->bottom_value('_fraction', $sheet, '1.0'));
61+
$qtype = $this->bottom_value('_qtype', $sheet, 'numerical');
62+
$keys = $this->process_data($sheet);
63+
$countQuestions = max(array_map(fn ($item) => count($item), $keys));
64+
65+
debugging("Try import {$countQuestions} questions", DEBUG_DEVELOPER);
66+
67+
for ($i = 0; $i < $countQuestions; $i++) {
68+
$qtext = $this->bottom_value('_text', $sheet, '');
6669

6770
foreach ($keys as $key => $value) {
68-
if($key === '_answer') {
69-
debugging("Skip _answer to be processed", DEBUG_DEVELOPER);
71+
if ($key === '_answer') {
72+
debugging('Skip _answer to be processed', DEBUG_DEVELOPER);
7073
continue;
7174
}
72-
$questiontext .= "<p><b>{$key}</b>: {$value[$i]}</p>";
75+
76+
$qtext .= "<p><b>{$key}</b>: {$value[$i]}</p>";
7377
}
7478

7579
foreach ($images as $image) {
76-
$questiontext .= "<img title=\"{$image['name']}\" src=\"data:{$image['mimetype']};base64,{$image['base64']}\"/>";
80+
$qtext .= "<img title=\"{$image['name']}\" src=\"data:{$image['mimetype']};base64,{$image['base64']}\"/>";
7781
}
7882

7983
$q = $this->defaultquestion();
8084
$q->id = $i;
8185
$q->name = $name;
82-
$q->questiontext = $questiontext;
83-
$q->qtype = 'shortanswer';
86+
$q->questiontext = $qtext;
87+
$q->qtype = $qtype;
8488
$q->feedback = [
8589
0 => [
8690
'text' => ' ',
8791
'format' => FORMAT_HTML,
8892
],
8993
];
9094

91-
$q->fraction = [1];
92-
$q->answer = [$keys['_answer'][$i]];
93-
$allQuestions[] = $q;
94-
}
95+
$q->fraction = [$fraction];
96+
$q->answer = [$keys['_answer'][$i]];
97+
$q->tolerance = [$fine];
98+
$q->penalty = $penalty;
99+
$qa[] = $q;
100+
}//end for
101+
}//end foreach
102+
103+
return $qa;
104+
105+
}//end readquestions()
106+
107+
108+
private function abs_val($str)
109+
{
110+
if (str_contains($str, '%')) {
111+
return (floatval($str) / 100);
95112
}
96113

97-
return $allQuestions;
98-
}
114+
return floatval($str);
115+
116+
}//end abs_val()
99117

100118

101119
private function process_data($data)
102120
{
103-
$count = $this->get_counts($data);
121+
$count = $this->get_counts($data);
104122
$countColumns = $count[0];
105-
$countRows = $count[1];
123+
$countRows = $count[1];
106124

107125
$keys = [];
108-
for($j = 0; $j < $countColumns; $j++) {
126+
for ($j = 0; $j < $countColumns; $j++) {
109127
$keys[$data[0][$j]] = [];
110128
}
111-
for($i = 1; $i < $countRows; $i++) {
112-
for($j = 0; $j < $countColumns; $j++) {
129+
130+
for ($i = 1; $i < $countRows; $i++) {
131+
for ($j = 0; $j < $countColumns; $j++) {
113132
$keys[$data[0][$j]][] = $data[$i][$j];
114133
}
115134
}
135+
116136
return $keys;
117-
}
137+
138+
}//end process_data()
139+
118140

119141
private function get_counts($data)
120142
{
121-
$countRows = 0;
143+
$countRows = 0;
122144
$countColumns = 0;
123145

124-
foreach($data[0] as $i => $column) {
125-
if(empty($column)) {
146+
foreach ($data[0] as $i => $column) {
147+
if (empty($column)) {
126148
break;
127149
}
128-
$countColumns = $i + 1;
150+
151+
$countColumns = ($i + 1);
129152
}
130153

131-
foreach($data as $i => $row) {
154+
foreach ($data as $i => $row) {
132155
$countEmpty = 0;
133-
for($j = 0; $j < $countColumns; $j++) {
156+
for ($j = 0; $j < $countColumns; $j++) {
134157
$cell = $row[$j];
135-
if(empty($cell)) {
158+
if (empty($cell)) {
136159
$countEmpty++;
137160
}
138161
}
139-
if($countEmpty >= $countColumns) {
162+
163+
if ($countEmpty >= $countColumns) {
140164
debugging("Found empty row $countEmpty >= $countColumns, at row $i", DEBUG_DEVELOPER);
141165
break;
142166
}
143-
for($j = 0 ; $j < $countColumns; $j++) {
167+
168+
for ($j = 0; $j < $countColumns; $j++) {
144169
$cell = $row[$j];
145-
if(!empty($cell)) {
146-
$countRows = $i + 1;
170+
if (!empty($cell)) {
171+
$countRows = ($i + 1);
147172
}
148173
}
149-
}
174+
}//end foreach
150175

151-
debugging("Columns: " . $countColumns, DEBUG_DEVELOPER);
152-
debugging("Rows: " . $countRows, DEBUG_DEVELOPER);
153-
return [$countColumns, $countRows];
154-
}
176+
debugging('Columns: '.$countColumns, DEBUG_DEVELOPER);
177+
debugging('Rows: '.$countRows, DEBUG_DEVELOPER);
178+
return [
179+
$countColumns,
180+
$countRows,
181+
];
155182

183+
}//end get_counts()
156184

157-
private function bottom_value($identifier, $data)
185+
186+
private function bottom_value($identifier, $data, $default = '')
158187
{
159188
foreach ($data as $i => $row) {
160189
foreach ($row as $j => $value) {
161190
if ($value === $identifier) {
162-
$r = $data[$i + 1][$j];
191+
$r = $data[($i + 1)][$j];
163192
debugging("Found $identifier, bottom value: {$r}", DEBUG_DEVELOPER);
164193
return $r;
165194
}
166195
}
167196
}
168-
debugging("Not found bottom value", DEBUG_DEVELOPER);
169-
return "";
170-
}
197+
198+
debugging('Not found bottom value', DEBUG_DEVELOPER);
199+
return $default;
200+
201+
}//end bottom_value()
202+
171203

172204
public function export_file_extension()
173205
{
174206
return '.xlsx';
175207

176-
}
208+
}//end export_file_extension()
177209

178210

179211
public function writequestion($question)
180212
{
181213
$this->lessonquestions[] = $question;
182214
return true;
183215

184-
}
216+
}//end writequestion()
185217

186218

187219
public function presave_process($content)
@@ -190,6 +222,8 @@ public function presave_process($content)
190222
throw new moodle_exception('noquestions', 'qformat_xlsxtable');
191223
}
192224

225+
debugging('Questions: '.print_r($this->lessonquestions, true), DEBUG_DEVELOPER);
226+
193227
$workbook = new MoodleExcelWorkbook($this->filename);
194228
$worksheet = $workbook->add_worksheet('Questions');
195229
foreach ($this->lessonquestions as $rowIndex => $question) {
@@ -203,18 +237,20 @@ public function presave_process($content)
203237

204238
$workbook->close();
205239
return true;
206-
}
240+
241+
}//end presave_process()
242+
207243

208244
public function readdata($filename)
209245
{
210246
if ($filename === null || !preg_match('#\.xlsx$#i', $filename)) {
211247
return false;
212248
}
213249

214-
$reader = IOFactory::createReader('Xlsx');
250+
$reader = IOFactory::createReader('Xlsx');
215251
$spreadsheet = $reader->load($filename);
216252

217-
$data = [];
253+
$data = [];
218254
$sheetCount = $spreadsheet->getSheetCount();
219255
for ($sheetIndex = 0; $sheetIndex < $sheetCount; $sheetIndex++) {
220256
$worksheet = $spreadsheet->getSheet($sheetIndex);
@@ -224,7 +260,7 @@ public function readdata($filename)
224260
$cellIterator->setIterateOnlyExistingCells(false);
225261
$rowData = [];
226262
foreach ($cellIterator as $cell) {
227-
$value = $cell->getCalculatedValue();
263+
$value = $cell->getCalculatedValue();
228264
$rowData[] = $value;
229265
}
230266

@@ -239,18 +275,22 @@ public function readdata($filename)
239275
$imageData['coordinates'] = $drawing->getCoordinates();
240276
$imageData['name'] = $drawing->getName();
241277
$imageData['base64'] = base64_encode(file_get_contents($imagePath));
242-
$mimeType = 'image/png';
278+
$mimeType = 'image/png';
243279
if (function_exists('mime_content_type')) {
244280
$mimeType = mime_content_type($imagePath);
245281
}
282+
246283
$imageData['mimetype'] = $mimeType;
247284

248285
$sheetData['images'][] = $imageData;
249286
}
250287

251288
$data['sheets'][] = $sheetData;
252-
}
289+
}//end for
253290

254291
return $data;
255-
}
256-
}
292+
293+
}//end readdata()
294+
295+
296+
}//end class

0 commit comments

Comments
 (0)