@loaders.gl/tile-converter 4.3.0-alpha.4 → 4.3.0-alpha.5

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.
Files changed (51) hide show
  1. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +4 -1
  2. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
  3. package/dist/converter-cli.js +0 -13
  4. package/dist/converter.min.cjs +89 -89
  5. package/dist/deps-installer/deps-installer.js +1 -1
  6. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -1
  7. package/dist/i3s-converter/helpers/node-index-document.js +6 -14
  8. package/dist/i3s-converter/helpers/node-pages.d.ts +1 -1
  9. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
  10. package/dist/i3s-converter/helpers/node-pages.js +14 -40
  11. package/dist/i3s-converter/i3s-converter.d.ts +24 -23
  12. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  13. package/dist/i3s-converter/i3s-converter.js +60 -130
  14. package/dist/i3s-server/app.d.ts +2 -1
  15. package/dist/i3s-server/app.d.ts.map +1 -1
  16. package/dist/i3s-server/app.js +7 -10
  17. package/dist/i3s-server/bin/i3s-server.min.cjs +71 -71
  18. package/dist/i3s-server/bin/www.js +5 -0
  19. package/dist/index.cjs +82 -194
  20. package/dist/index.cjs.map +2 -2
  21. package/dist/lib/utils/statistic-utills.d.ts +4 -1
  22. package/dist/lib/utils/statistic-utills.d.ts.map +1 -1
  23. package/dist/lib/utils/statistic-utills.js +4 -23
  24. package/dist/pgm-loader.js +1 -1
  25. package/package.json +19 -20
  26. package/src/3d-tiles-converter/3d-tiles-converter.ts +2 -1
  27. package/src/converter-cli.ts +0 -19
  28. package/src/i3s-converter/helpers/node-index-document.ts +16 -26
  29. package/src/i3s-converter/helpers/node-pages.ts +20 -46
  30. package/src/i3s-converter/i3s-converter.ts +88 -154
  31. package/src/i3s-server/app.ts +7 -10
  32. package/src/i3s-server/bin/www.ts +6 -0
  33. package/src/lib/utils/statistic-utills.ts +5 -27
  34. package/bin/slpk-extractor.js +0 -2
  35. package/dist/i3s-server/controllers/index-controller.d.ts +0 -8
  36. package/dist/i3s-server/controllers/index-controller.d.ts.map +0 -1
  37. package/dist/i3s-server/controllers/index-controller.js +0 -31
  38. package/dist/i3s-server/routes/index.d.ts +0 -2
  39. package/dist/i3s-server/routes/index.d.ts.map +0 -1
  40. package/dist/i3s-server/routes/index.js +0 -17
  41. package/dist/slpk-extractor/slpk-extractor.d.ts +0 -23
  42. package/dist/slpk-extractor/slpk-extractor.d.ts.map +0 -1
  43. package/dist/slpk-extractor/slpk-extractor.js +0 -73
  44. package/dist/slpk-extractor-cli.d.ts +0 -17
  45. package/dist/slpk-extractor-cli.d.ts.map +0 -1
  46. package/dist/slpk-extractor-cli.js +0 -105
  47. package/dist/slpk-extractor.min.cjs +0 -344
  48. package/src/i3s-server/controllers/index-controller.ts +0 -32
  49. package/src/i3s-server/routes/index.ts +0 -18
  50. package/src/slpk-extractor/slpk-extractor.ts +0 -102
  51. package/src/slpk-extractor-cli.ts +0 -136
@@ -4,5 +4,8 @@
4
4
  * @returns string representation of the time
5
5
  */
6
6
  export declare function timeConverter(time: number | [number, number]): string;
7
- export declare function calculateFilesSize(params: any): Promise<number | null>;
7
+ export declare function calculateFilesSize(params: {
8
+ outputPath: string;
9
+ tilesetName: string;
10
+ }): Promise<number | null>;
8
11
  //# sourceMappingURL=statistic-utills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"statistic-utills.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/statistic-utills.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAarE;AA6BD,wBAAsB,kBAAkB,CAAC,MAAM,KAAA,0BAkB9C"}
1
+ {"version":3,"file":"statistic-utills.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/statistic-utills.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAarE;AA6BD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAC,0BAYzF"}
@@ -42,34 +42,15 @@ function timeConverterFromSecondsAndMilliseconds(timeInSeconds, milliseconds) {
42
42
  return result;
43
43
  }
44
44
  export async function calculateFilesSize(params) {
45
- const { slpk, outputPath, tilesetName } = params;
45
+ const { outputPath, tilesetName } = params;
46
46
  const fullOutputPath = getAbsoluteFilePath(outputPath);
47
47
  try {
48
- if (slpk) {
49
- const slpkPath = join(fullOutputPath, `${tilesetName}.slpk`);
50
- const stat = await fs.stat(slpkPath);
51
- return stat.size;
52
- }
53
- const directoryPath = join(fullOutputPath, tilesetName);
54
- const totalSize = await getTotalFilesSize(directoryPath);
55
- return totalSize;
48
+ const slpkPath = join(fullOutputPath, `${tilesetName}.slpk`);
49
+ const stat = await fs.stat(slpkPath);
50
+ return stat.size;
56
51
  }
57
52
  catch (error) {
58
53
  console.log('Calculate file sizes error: ', error); // eslint-disable-line
59
54
  return null;
60
55
  }
61
56
  }
62
- async function getTotalFilesSize(dirPath) {
63
- let totalFileSize = 0;
64
- const files = await fs.readdir(dirPath);
65
- for (const file of files) {
66
- const fileStat = await fs.stat(join(dirPath, file));
67
- if (fileStat.isDirectory()) {
68
- totalFileSize += await getTotalFilesSize(join(dirPath, file));
69
- }
70
- else {
71
- totalFileSize += fileStat.size;
72
- }
73
- }
74
- return totalFileSize;
75
- }
@@ -1,7 +1,7 @@
1
1
  import { Geoid, parsePGM } from '@math.gl/geoid';
2
2
  // __VERSION__ is injected by babel-plugin-version-inline
3
3
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
4
- const VERSION = typeof "4.3.0-alpha.3" !== 'undefined' ? "4.3.0-alpha.3" : 'latest';
4
+ const VERSION = typeof "4.3.0-alpha.4" !== 'undefined' ? "4.3.0-alpha.4" : 'latest';
5
5
  export { Geoid };
6
6
  /**
7
7
  * Loader for PGM - Netpbm grayscale image format
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/tile-converter",
3
- "version": "4.3.0-alpha.4",
3
+ "version": "4.3.0-alpha.5",
4
4
  "description": "Converter",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,6 @@
29
29
  "sideEffects": false,
30
30
  "bin": {
31
31
  "i3s-server": "./bin/i3s-server.js",
32
- "slpk-extractor": "./bin/slpk-extractor.js",
33
32
  "tile-converter": "./bin/converter.js"
34
33
  },
35
34
  "files": [
@@ -46,27 +45,26 @@
46
45
  "process": false
47
46
  },
48
47
  "scripts": {
49
- "pre-build": "npm run build-converter-bundle && npm run build-slpk-extractor-bundle && npm run build-i3s-server-bundle && npm run copy-certificates",
48
+ "pre-build": "npm run build-converter-bundle && npm run build-i3s-server-bundle && npm run copy-certificates",
50
49
  "build-converter-bundle": "esbuild src/converter-cli.ts --outfile=dist/converter.min.cjs --platform=node --target=esnext,node14 --external:join-images --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
51
- "build-slpk-extractor-bundle": "esbuild src/slpk-extractor-cli.ts --outfile=dist/slpk-extractor.min.cjs --platform=node --target=esnext,node14 --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
52
50
  "build-i3s-server-bundle": "esbuild src/i3s-server/bin/www.ts --outfile=dist/i3s-server/bin/i3s-server.min.cjs --platform=node --target=esnext,node14 --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
53
51
  "copy-certificates": "cp -R src/i3s-server/certs dist/i3s-server"
54
52
  },
55
53
  "dependencies": {
56
- "@loaders.gl/3d-tiles": "4.3.0-alpha.4",
57
- "@loaders.gl/compression": "4.3.0-alpha.4",
58
- "@loaders.gl/crypto": "4.3.0-alpha.4",
59
- "@loaders.gl/draco": "4.3.0-alpha.4",
60
- "@loaders.gl/gltf": "4.3.0-alpha.4",
61
- "@loaders.gl/i3s": "4.3.0-alpha.4",
62
- "@loaders.gl/images": "4.3.0-alpha.4",
63
- "@loaders.gl/loader-utils": "4.3.0-alpha.4",
64
- "@loaders.gl/math": "4.3.0-alpha.4",
65
- "@loaders.gl/polyfills": "4.3.0-alpha.4",
66
- "@loaders.gl/textures": "4.3.0-alpha.4",
67
- "@loaders.gl/tiles": "4.3.0-alpha.4",
68
- "@loaders.gl/worker-utils": "4.3.0-alpha.4",
69
- "@loaders.gl/zip": "4.3.0-alpha.4",
54
+ "@loaders.gl/3d-tiles": "4.3.0-alpha.5",
55
+ "@loaders.gl/compression": "4.3.0-alpha.5",
56
+ "@loaders.gl/crypto": "4.3.0-alpha.5",
57
+ "@loaders.gl/draco": "4.3.0-alpha.5",
58
+ "@loaders.gl/gltf": "4.3.0-alpha.5",
59
+ "@loaders.gl/i3s": "4.3.0-alpha.5",
60
+ "@loaders.gl/images": "4.3.0-alpha.5",
61
+ "@loaders.gl/loader-utils": "4.3.0-alpha.5",
62
+ "@loaders.gl/math": "4.3.0-alpha.5",
63
+ "@loaders.gl/polyfills": "4.3.0-alpha.5",
64
+ "@loaders.gl/textures": "4.3.0-alpha.5",
65
+ "@loaders.gl/tiles": "4.3.0-alpha.5",
66
+ "@loaders.gl/worker-utils": "4.3.0-alpha.5",
67
+ "@loaders.gl/zip": "4.3.0-alpha.5",
70
68
  "@math.gl/core": "^4.0.0",
71
69
  "@math.gl/culling": "^4.0.0",
72
70
  "@math.gl/geoid": "^4.0.0",
@@ -89,10 +87,11 @@
89
87
  "sharp": "^0.31.3"
90
88
  },
91
89
  "devDependencies": {
92
- "@types/express": "^4.17.17"
90
+ "@types/express": "^4.17.17",
91
+ "@types/inquirer": "^9.0.7"
93
92
  },
94
93
  "peerDependencies": {
95
94
  "@loaders.gl/core": "^4.0.0"
96
95
  },
97
- "gitHead": "4900ac4c4de20366c050b80cef04dc5b52d167af"
96
+ "gitHead": "b57553345b3cbf621c95ad9b22aa672217451f61"
98
97
  }
@@ -29,6 +29,7 @@ import {I3SLoaderOptions} from '@loaders.gl/i3s/src/i3s-loader';
29
29
  import {ZipFileSystem} from '../../../zip/src';
30
30
  import {ConversionDump, ConversionDumpOptions} from '../lib/utils/conversion-dump';
31
31
  import {Progress} from '../i3s-converter/helpers/progress';
32
+ import {PromptModule} from 'inquirer';
32
33
 
33
34
  const I3S = 'I3S';
34
35
 
@@ -88,7 +89,7 @@ export default class Tiles3DConverter {
88
89
  tilesetName: string;
89
90
  maxDepth?: number;
90
91
  egmFilePath: string;
91
- inquirer?: Promise<unknown>;
92
+ inquirer?: {prompt: PromptModule};
92
93
  analyze?: boolean;
93
94
  }): Promise<string | undefined> {
94
95
  if (isBrowser) {
@@ -30,8 +30,6 @@ type TileConversionOptions = {
30
30
  instantNodeWriting: boolean;
31
31
  /** Try to merge similar materials to be able to merge meshes into one node (I3S to 3DTiles conversion only) */
32
32
  mergeMaterials: boolean;
33
- /** 3DTiles->I3S only. location of 7z.exe archiver to create slpk on Windows OS, default: "C:\Program Files\7-Zip\7z.exe" */
34
- sevenZipExe: string;
35
33
  /** location of the Earth Gravity Model (*.pgm) file to convert heights from ellipsoidal to gravity-related format,
36
34
  * default: "./deps/egm2008-5.pgm". A model file can be loaded from GeographicLib
37
35
  * https://geographiclib.sourceforge.io/html/geoid.html */
@@ -54,8 +52,6 @@ type TileConversionOptions = {
54
52
  validate: boolean;
55
53
  /** Maximal depth of the hierarchical tiles tree traversal, default: infinite */
56
54
  maxDepth?: number;
57
- /** 3DTiles->I3S only. Whether the converter generates *.slpk (Scene Layer Package) I3S output file */
58
- slpk: boolean;
59
55
  /** adds hash file to the slpk if there's no one */
60
56
  addHash: boolean;
61
57
  /** Feature metadata class from EXT_FEATURE_METADATA or EXT_STRUCTURAL_METADATA extensions */
@@ -178,14 +174,10 @@ function printHelp(): void {
178
174
  console.log(
179
175
  '--split-nodes [Prevent to merge similar materials that could lead to incorrect visualization (I3S to 3DTiles conversion only)]'
180
176
  );
181
- console.log('--slpk [Generate slpk (Scene Layer Packages) I3S output file]');
182
177
  console.log(
183
178
  '--tileset [tileset.json file (3DTiles) / http://..../SceneServer/layers/0 resource (I3S)]'
184
179
  );
185
180
  console.log('--input-type [tileset input type: I3S or 3DTILES]');
186
- console.log(
187
- '--7zExe [location of 7z.exe archiver to create slpk on Windows, default: "C:\\Program Files\\7-Zip\\7z.exe"]'
188
- );
189
181
  console.log(
190
182
  '--egm [location of Earth Gravity Model *.pgm file to convert heights from ellipsoidal to gravity-related format. A model file can be loaded from GeographicLib https://geographiclib.sourceforge.io/html/geoid.html], default: "./deps/egm2008-5.zip"'
191
183
  );
@@ -236,8 +228,6 @@ async function convert(options: ValidatedTileConversionOptions) {
236
228
  outputPath: options.output,
237
229
  tilesetName: options.name,
238
230
  maxDepth: options.maxDepth,
239
- slpk: options.slpk,
240
- sevenZipExe: options.sevenZipExe,
241
231
  egmFilePath: options.egm,
242
232
  token: options.token,
243
233
  draco: options.draco,
@@ -277,7 +267,6 @@ function validateOptions(
277
267
  condition: (value: any) => addHash || Boolean(value) || Boolean(options.analyze)
278
268
  },
279
269
  output: {getMessage: () => console.log('Missed: --output [Output path name]')},
280
- sevenZipExe: {getMessage: () => console.log('Missed: --7zExe [7z archiver executable path]')},
281
270
  egm: {getMessage: () => console.log('Missed: --egm [*.pgm earth gravity model file path]')},
282
271
  tileset: {getMessage: () => console.log('Missed: --tileset [tileset.json file]')},
283
272
  inputType: {
@@ -315,14 +304,12 @@ function parseOptions(args: string[]): TileConversionOptions {
315
304
  output: 'data',
316
305
  instantNodeWriting: false,
317
306
  mergeMaterials: true,
318
- sevenZipExe: 'C:\\Program Files\\7-Zip\\7z.exe',
319
307
  egm: join(process.cwd(), 'deps', 'egm2008-5.pgm'),
320
308
  draco: true,
321
309
  installDependencies: false,
322
310
  generateTextures: false,
323
311
  generateBoundingVolumes: false,
324
312
  validate: false,
325
- slpk: false,
326
313
  addHash: false,
327
314
  quiet: false,
328
315
  noEgm: false
@@ -353,15 +340,9 @@ function parseOptions(args: string[]): TileConversionOptions {
353
340
  case '--max-depth':
354
341
  opts.maxDepth = getIntegerValue(index, args);
355
342
  break;
356
- case '--slpk':
357
- opts.slpk = getBooleanValue(index, args);
358
- break;
359
343
  case '--add-hash':
360
344
  opts.addHash = getBooleanValue(index, args);
361
345
  break;
362
- case '--7zExe':
363
- opts.sevenZipExe = getStringValue(index, args);
364
- break;
365
346
  case '--egm':
366
347
  opts.egm = getStringValue(index, args);
367
348
  break;
@@ -8,7 +8,7 @@ import {
8
8
  } from '@loaders.gl/i3s';
9
9
  import transform from 'json-map-transform';
10
10
  import {v4 as uuidv4} from 'uuid';
11
- import {openJson, writeFile, writeFileForSlpk} from '../../lib/utils/file-utils';
11
+ import {openJson, writeFileForSlpk} from '../../lib/utils/file-utils';
12
12
  import I3SConverter from '../i3s-converter';
13
13
  import {NODE as nodeTemplate} from '../json-templates/node';
14
14
  import {I3SConvertedResources} from '../types';
@@ -155,27 +155,20 @@ export class NodeIndexDocument {
155
155
  */
156
156
  private async write(node: Node3DIndexDocument): Promise<void> {
157
157
  const path = join(this.converter.layers0Path, 'nodes', this.id);
158
- if (this.converter.options.slpk) {
159
- await this.converter.writeQueue.enqueue(
160
- {
161
- archiveKey: `nodes/${this.id}/3dNodeIndexDocument.json.gz`,
162
- writePromise: () =>
163
- writeFileForSlpk(
164
- path,
165
- JSON.stringify(node),
166
- '3dNodeIndexDocument.json',
167
- true,
168
- this.converter.compressList
169
- )
170
- },
171
- true
172
- );
173
- } else {
174
- await this.converter.writeQueue.enqueue(
175
- {writePromise: () => writeFile(path, JSON.stringify(node))},
176
- true
177
- );
178
- }
158
+ await this.converter.writeQueue.enqueue(
159
+ {
160
+ archiveKey: `nodes/${this.id}/3dNodeIndexDocument.json.gz`,
161
+ writePromise: () =>
162
+ writeFileForSlpk(
163
+ path,
164
+ JSON.stringify(node),
165
+ '3dNodeIndexDocument.json',
166
+ true,
167
+ this.converter.compressList
168
+ )
169
+ },
170
+ true
171
+ );
179
172
  }
180
173
 
181
174
  /**
@@ -188,10 +181,7 @@ export class NodeIndexDocument {
188
181
  }
189
182
  const path = this.id;
190
183
  const parentNodePath = join(this.converter.layers0Path, 'nodes', path);
191
- let parentNodeFileName = 'index.json';
192
- if (this.converter.options.slpk) {
193
- parentNodeFileName = '3dNodeIndexDocument.json';
194
- }
184
+ const parentNodeFileName = '3dNodeIndexDocument.json';
195
185
  return (await openJson(parentNodePath, parentNodeFileName)) as Node3DIndexDocument;
196
186
  }
197
187
 
@@ -51,7 +51,7 @@ export default class NodePages {
51
51
  * @param writeFileFunc - function to save one nodePage into a file
52
52
  * @param nodesPerPage - length limit for one nodePage. An additional nodePage is created when this limit is met
53
53
  */
54
- constructor(writeFileFunc, nodesPerPage, converter: I3SConverter) {
54
+ constructor(writeFileFunc, nodesPerPage: number, converter: I3SConverter) {
55
55
  this.nodesPerPage = nodesPerPage;
56
56
  this.nodesCounter = 0;
57
57
  // @ts-expect-error
@@ -75,16 +75,9 @@ export default class NodePages {
75
75
  * @param nodePageId - node page id
76
76
  * @returns file path and file name
77
77
  */
78
- private getNodePageFileName(nodePageId): {filePath: string; fileName: string} {
79
- let filePath;
80
- let fileName;
81
- if (this.converter.options.slpk) {
82
- filePath = join(this.converter.layers0Path, 'nodepages');
83
- fileName = `${nodePageId.toString()}.json`;
84
- } else {
85
- filePath = join(this.converter.layers0Path, 'nodepages', nodePageId.toString());
86
- fileName = 'index.json';
87
- }
78
+ private getNodePageFileName(nodePageId: number): {filePath: string; fileName: string} {
79
+ const filePath = join(this.converter.layers0Path, 'nodepages');
80
+ const fileName = `${nodePageId.toString()}.json`;
88
81
  return {filePath, fileName};
89
82
  }
90
83
 
@@ -190,23 +183,14 @@ export default class NodePages {
190
183
  nodePage.nodes.push(node);
191
184
  }
192
185
  const nodePageStr = JSON.stringify(nodePage);
193
- if (this.converter.options.slpk) {
194
- await this.converter.writeQueue.enqueue(
195
- {
196
- archiveKey: `nodePages/${nodePageIndex.toString()}.json.gz`,
197
- writePromise: () =>
198
- this.writeFile(filePath, nodePageStr, fileName, true, this.converter.compressList)
199
- },
200
- true
201
- );
202
- } else {
203
- await this.converter.writeQueue.enqueue(
204
- {
205
- writePromise: () => this.writeFile(filePath, nodePageStr)
206
- },
207
- true
208
- );
209
- }
186
+ await this.converter.writeQueue.enqueue(
187
+ {
188
+ archiveKey: `nodePages/${nodePageIndex.toString()}.json.gz`,
189
+ writePromise: () =>
190
+ this.writeFile(filePath, nodePageStr, fileName, true, this.converter.compressList)
191
+ },
192
+ true
193
+ );
210
194
  }
211
195
 
212
196
  /**
@@ -236,25 +220,15 @@ export default class NodePages {
236
220
  await this.saveMetadata();
237
221
  return;
238
222
  }
239
- if (this.converter.options.slpk) {
240
- for (const [index, nodePage] of this.nodePages.entries()) {
241
- const nodePageStr = JSON.stringify(nodePage);
242
- const slpkPath = join(this.converter.layers0Path, 'nodepages');
243
- await this.converter.writeQueue.enqueue({
244
- archiveKey: `nodePages/${index.toString()}.json.gz`,
245
- writePromise: () => this.writeFile(slpkPath, nodePageStr, `${index.toString()}.json`)
246
- });
247
- }
248
- await this.saveMetadata();
249
- } else {
250
- for (const [index, nodePage] of this.nodePages.entries()) {
251
- const nodePageStr = JSON.stringify(nodePage);
252
- const nodePagePath = join(this.converter.layers0Path, 'nodepages', index.toString());
253
- await this.converter.writeQueue.enqueue({
254
- writePromise: () => this.writeFile(nodePagePath, nodePageStr)
255
- });
256
- }
223
+ for (const [index, nodePage] of this.nodePages.entries()) {
224
+ const nodePageStr = JSON.stringify(nodePage);
225
+ const slpkPath = join(this.converter.layers0Path, 'nodepages');
226
+ await this.converter.writeQueue.enqueue({
227
+ archiveKey: `nodePages/${index.toString()}.json.gz`,
228
+ writePromise: () => this.writeFile(slpkPath, nodePageStr, `${index.toString()}.json`)
229
+ });
257
230
  }
231
+ await this.saveMetadata();
258
232
  }
259
233
 
260
234
  /**