squareOne.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /*
  2. let gameSquareOne = {
  3. create: function(){},
  4. update: function(){},
  5. ---------------------------- end of phaser functions
  6. func_updateCounter: function(){},
  7. func_overSquare: function(){},
  8. func_outSquare: function(){},
  9. func_clickSquare: function(){},
  10. //func_setPlace: function(){},
  11. func_postScore: function(){},
  12. func_viewHelp: function(){},
  13. //func_checkOverlap: function(){}
  14. //func_getRndDivisor: function(){}
  15. };
  16. */
  17. // Tractor and Square states
  18. let gameSquareOne = {
  19. create: function() {
  20. //timer
  21. totalTime = 0;
  22. timer = game.time.create(false);
  23. timer.loop(1000, this.func_updateCounter, this);
  24. timer.start();
  25. detail="";
  26. // Background
  27. game.add.image(0, 0, 'bgimage');
  28. // Calls function that loads navigation icons
  29. iconSettings["func_addButtons"](true,true,
  30. true,true,true,
  31. true,false,
  32. 'difficulty', this.func_viewHelp);
  33. // Clouds
  34. game.add.image(300, 100, 'cloud');
  35. game.add.image(660, 80, 'cloud');
  36. game.add.image(110, 85, 'cloud').scale.setTo(0.8);
  37. // Font styles for labels
  38. const stylePlace = { font: '26px Arial', fill: '#400080', align: 'center'};
  39. const styleLabel = { font: '26px Arial', fill: '#000080', align: 'center'};
  40. const styleFraction = { font: '15px Arial', fill: '#000080', align: 'center'};
  41. //Initial tractor and place position
  42. let startX = 170;
  43. if(levelOperator=='Minus') startX = 730;
  44. startX = startX; //Workaround for initial position inside update
  45. // Width and height of blocks and 'floor gaps'
  46. const blockWidth = 80;
  47. const blockHeight = 40;
  48. // Floor gaps
  49. for(let i=0;i<9;i++){
  50. game.add.image(i*100, 501, 'floor');
  51. }
  52. //Control variables
  53. clicked = false; //Floor blocks or apilled blocks clicked
  54. hideLabels = false; //Labels of blocks
  55. animate = false; //Start move animation
  56. checkCollide = false; //Check if tractor fon't any block left or floor hole
  57. result = false; //Game is correct
  58. move = false; //Continue tractor animation
  59. moveCounter = 0; //Move counter
  60. moveEnd = 140; //Move end counter
  61. //tractor
  62. let tractorAlign = -80;
  63. if(levelOperator=='Minus'){
  64. tractorAlign *= -1;
  65. }
  66. tractor = game.add.sprite(startX+tractorAlign, 445, 'tractor');
  67. tractor.anchor.setTo(0.5, 0.5);
  68. tractor.scale.setTo(0.8);
  69. tractor.animations.add('right',[0,1,2,3,4]);
  70. if(levelOperator=='Minus'){
  71. tractor.scale.x *= -1;
  72. }
  73. //generator
  74. //Blocks and fractions
  75. if(debugMode) console.log("pos " +levelPosition); // position in the game map
  76. maxBlocks = levelPosition+4; //Maximum blocks
  77. if(levelType=='B' || levelOperator=='Mixed') maxBlocks = 10;
  78. blocks = game.add.group(); //Fraction arrays (apilled)
  79. numBlocks = game.rnd.integerInRange(levelPosition+2, maxBlocks); //Number of blocks
  80. if(debugMode) console.log("num " + numBlocks+", min " + (levelPosition+2) + ", max " + maxBlocks);
  81. curBlock = 0; //Actual index block
  82. blockDirection = []; //Directions right(plus), left (minus)
  83. blockDistance = []; //Displacement distance of the blocks
  84. blockLabel = game.add.group(); //Labels of the blocks
  85. blockSeparator = game.add.group(); //Separator of the labels
  86. //blockAngle = []; //Angles of blocks
  87. //blockTraceColor = []; //Trace colors
  88. endPosition = startX; //Ending position, accumulative
  89. if(levelOperator=='Minus') endPosition -= blockWidth;
  90. else endPosition += blockWidth;
  91. //Game A exclusive variables
  92. floorBlocks = game.add.group(); //Selectable floor blocks
  93. floorIndex = -1; //Selected floor block
  94. floorCount = 8; //Number of floor blocks
  95. floorClicked = false; //If clicked portion of floor
  96. curFloor = -1;
  97. //Game B exclusive variables
  98. arrowPlace = startX; //Fixed place for help arrow
  99. if(levelOperator=='Minus') arrowPlace -= blockWidth;
  100. else arrowPlace += blockWidth;
  101. fractionClicked = false; //If clicked a fraction (game B)
  102. fractionIndex = -1; //Index of clicked fraction (game B)
  103. hasFigure = false;
  104. for(let p=0;p<numBlocks;p++){
  105. let portion = game.rnd.integerInRange(1, levelDifficulty); //Portion of the square, according to difficulty
  106. if(portion==3) detail+= "4,";
  107. else detail += portion+",";
  108. if(portion==levelDifficulty) hasFigure = true;
  109. let direction = '';
  110. let lineColor = '';
  111. if(levelOperator=='Plus'){
  112. direction = 'Right';
  113. lineColor = 0x31314e; //plus block: "black'
  114. }else if(levelOperator=='Minus'){
  115. direction = 'Left';
  116. lineColor = 0xb30000;//minus block : "red"
  117. }
  118. //blocks close to tractor
  119. let block = game.add.graphics(startX, 460-p*blockHeight);
  120. block.anchor.setTo(0.5, 0.5);
  121. block.lineStyle(2, lineColor);
  122. block.beginFill(0xefeff5);
  123. blockDirection[p] = direction;
  124. if(portion==1){
  125. block.drawRect(0, 0, blockWidth, blockHeight);
  126. blockDistance.push(blockWidth);
  127. //blockAngle.push(360);
  128. if(levelLabel){
  129. let labelX = startX;
  130. if(levelOperator=='Minus') labelX -= (15+blockWidth);
  131. else labelX += blockWidth+15;
  132. let label = game.add.text(labelX, 480-p*blockHeight, portion , styleLabel);
  133. label.anchor.setTo(0.5, 0.5);
  134. blockLabel.add(label);
  135. }
  136. }else{
  137. if(portion==3) portion = 4;
  138. let distance = blockWidth/portion;
  139. block.drawRect(0, 0, distance, blockHeight);
  140. blockDistance.push(distance);
  141. if(levelLabel){
  142. let labelX = startX;
  143. if(levelOperator=='Minus') labelX -= (15+distance);
  144. else labelX += 15+distance;
  145. let separator = game.add.sprite(labelX, 480-p*blockHeight, 'separator');
  146. separator.scale.setTo(0.6);
  147. separator.anchor.setTo(0.5, 0.5);
  148. blockSeparator.add(separator);
  149. let label = game.add.text(labelX, 483-p*blockHeight, '1\n'+portion , styleFraction);
  150. label.anchor.setTo(0.5, 0.5);
  151. blockLabel.add(label);
  152. }
  153. }
  154. if(direction=='Right'){
  155. endPosition += Math.floor(blockWidth/portion);
  156. }else if(direction=='Left'){
  157. endPosition -= Math.floor(blockWidth/portion);
  158. block.scale.x *= -1;
  159. }
  160. block.endFill();
  161. //If game is type B, (select fractions, adding event)
  162. if(levelType=='B'){
  163. block.alpha = 0.5;
  164. block.inputEnabled = true;
  165. block.input.useHandCursor = true;
  166. block.events.onInputDown.add(this.func_clickSquare, {indice: p});
  167. block.events.onInputOver.add(this.func_overSquare, {indice: p});
  168. block.events.onInputOut.add(this.func_outSquare, {indice: p});
  169. }
  170. blocks.add(block);
  171. }
  172. //Calculate next block
  173. if(blockDirection[curBlock]=='Right'){
  174. nextEnd = startX+blockDistance[curBlock];
  175. }else{
  176. nextEnd = startX-blockDistance[curBlock];
  177. }
  178. //If end position is out of bounds, restart
  179. if(!hasFigure) game.state.start('gameSquareOne');
  180. if (levelOperator=='Plus' && (endPosition<(startX+blockWidth) || endPosition>(startX+8*blockWidth))){
  181. game.state.start('gameSquareOne');
  182. }else if (levelOperator=='Minus' && (endPosition>(startX) || endPosition<(startX-(8*blockWidth)))){
  183. game.state.start('gameSquareOne');
  184. }
  185. //If game is type B, selectiong a random block floor place
  186. if(levelType=='B'){
  187. let end = game.rnd.integerInRange(1, numBlocks);
  188. for(let i=0;i<end;i++){
  189. if(blockDirection[i]=='Right')
  190. arrowPlace += blockDistance[i];
  191. else if(blockDirection[i]=='Left')
  192. arrowPlace -= blockDistance[i];
  193. }
  194. }
  195. //Selectable floor
  196. floorCount = 8*levelDifficulty;
  197. let widFloor = blockWidth/levelDifficulty;
  198. if(levelDifficulty==3){
  199. floorCount = 8*4;
  200. widFloor = blockWidth/4;
  201. }
  202. for(let i = 0; i < floorCount; i++){
  203. let posX = startX;
  204. if(levelOperator=='Minus') posX -= (blockWidth + i*widFloor);
  205. else posX += (blockWidth + i*widFloor);
  206. if(levelType=='B'){
  207. if(levelOperator=='Minus'){
  208. if(posX<=arrowPlace){
  209. floorCount = i+1;
  210. floorIndex = i-1;
  211. break;
  212. }
  213. }else{
  214. if(posX>=arrowPlace){
  215. floorCount = i+1;
  216. floorIndex = i-1;
  217. break;
  218. }
  219. }
  220. }
  221. // blocks on the floor
  222. let block = game.add.graphics(posX, 500);
  223. block.anchor.setTo(0.5, 0);
  224. block.lineStyle(0.9, 0xffffff);
  225. block.beginFill(0xa8c0e6);
  226. block.drawRect(0, 0, widFloor, blockHeight);
  227. block.endFill();
  228. if(levelOperator=='Minus') block.scale.x *= -1;
  229. if(levelType=="A"){
  230. block.alpha = 0.5;
  231. block.inputEnabled = true;
  232. block.input.useHandCursor = true;
  233. block.events.onInputDown.add(this.func_clickSquare, {indice: i});
  234. block.events.onInputOver.add(this.func_overSquare, {indice: i});
  235. block.events.onInputOut.add(this.func_outSquare, {indice: i});
  236. }
  237. floorBlocks.add(block);
  238. }
  239. for(let i=0;i<=8;i++){
  240. let posX = startX;
  241. if(levelOperator=='Minus')posX -= ((9-i)*blockWidth);
  242. else posX+=((i+1)*blockWidth);
  243. game.add.text(posX, 560, i , stylePlace).anchor.setTo(0.5, 0.5);
  244. }
  245. //ok and error images
  246. okImg = game.add.image(game.world.centerX, game.world.centerY, 'h_ok');
  247. okImg.anchor.setTo(0.5);
  248. okImg.alpha = 0;
  249. errorImg = game.add.image(game.world.centerX, game.world.centerY, 'h_error');
  250. errorImg.anchor.setTo(0.5);
  251. errorImg.alpha = 0;
  252. //Help arrow
  253. arrow = game.add.sprite(this.arrowPlace, 480, 'down');
  254. arrow.anchor.setTo(0.5, 0.5);
  255. if(levelType=="B")
  256. arrow.alpha = 0;
  257. else if(levelType=="A")
  258. arrow.alpha = 0.5;
  259. },
  260. update: function() {
  261. if(!clicked){
  262. if(!move){
  263. if(levelType=='A'){
  264. //Follow mouse
  265. if (game.physics.arcade.distanceToPointer(arrow, game.input.activePointer) > 8 )
  266. {
  267. let xPos = game.input.mousePointer.x;
  268. //set left limit to the arrow
  269. if (xPos < 250){
  270. xPos = 250;
  271. }
  272. arrow.x = xPos;
  273. }
  274. }
  275. }
  276. }
  277. //Start animation
  278. if(animate){
  279. if(blockDirection[curBlock]=='Right'){
  280. tractor.x+=2;
  281. }else if(blockDirection[curBlock]=='Left'){
  282. tractor.x-=2;
  283. }
  284. for(let i=0;i<numBlocks;i++){ //Moving every block
  285. if(blockDirection[curBlock]=='Right'){
  286. blocks.children[i].x +=2;
  287. }else{
  288. blocks.children[i].x -=2;
  289. }
  290. }
  291. let extra = 80-blockDistance[curBlock];
  292. if(blockDirection[curBlock]=='Right'){
  293. if(blocks.children[curBlock].x>=nextEnd+extra){
  294. blocks.children[curBlock].alpha = 0;
  295. blocks.y += 40;
  296. curBlock +=1;
  297. nextEnd += blockDistance[curBlock];
  298. for(let i=0; i<=floorIndex; i++ ){
  299. if(floorBlocks.children[i].x<(blocks.children[curBlock-1].x+blockDistance[curBlock-1])){
  300. floorBlocks.children[i].alpha = 0.2;
  301. curFloor = i;
  302. }
  303. }
  304. }
  305. }else if(blockDirection[curBlock]=='Left'){
  306. if(blocks.children[curBlock].x<=(nextEnd-extra)){
  307. blocks.children[curBlock].alpha = 0;
  308. blocks.y += 40;
  309. curBlock+=1;
  310. nextEnd -= blockDistance[curBlock];
  311. for(let i=0; i<=floorIndex; i++ ){
  312. if(floorBlocks.children[i].x>(blocks.children[curBlock-1].x-blockDistance[curBlock-1])){
  313. floorBlocks.children[i].alpha = 0.2;
  314. curFloor = i;
  315. }
  316. }
  317. }
  318. }
  319. if( curBlock>blockIndex || curFloor>=floorIndex){ //Final position
  320. animate= false;
  321. checkCollide = true;
  322. }
  323. }
  324. //Check if tractor has blocks left or floor holes
  325. if(checkCollide){
  326. tractor.animations.stop();
  327. timer.stop();
  328. //Check left blocks
  329. let resultBlock = true;
  330. for(let i=0; i<=blockIndex; i++){
  331. if(blocks.children[i].alpha==1) resultBlock = false;
  332. }
  333. //check floor Holes
  334. let resultFloor = true;
  335. for(let i=0; i<=floorIndex; i++){
  336. if(floorBlocks.children[i].alpha==1) resultFloor = false;
  337. }
  338. if(resultBlock && resultFloor){
  339. result = true;
  340. }else{
  341. result = false;
  342. }
  343. this.func_postScore();
  344. move = true;
  345. checkCollide = false;
  346. }
  347. //Continue moving animation
  348. if(move){
  349. if(moveCounter==0){
  350. if(result){
  351. tractor.animations.play('right', 6, true);
  352. if(audioStatus){
  353. okSound.play();
  354. }
  355. passedLevels++;
  356. if(debugMode) console.log("passedLevels = "+passedLevels);
  357. okImg.alpha = 1;
  358. }else{
  359. if(audioStatus){
  360. errorSound.play();
  361. }
  362. errorImg.alpha = 1;
  363. }
  364. }
  365. moveCounter += 1;
  366. if(result){
  367. if(levelOperator=='Minus'){
  368. tractor.x -=2;
  369. }else{
  370. tractor.x +=2;
  371. }
  372. }
  373. if(moveCounter>=moveEnd){
  374. if(result){
  375. levelMove = true;
  376. }else{
  377. levelMove = false;
  378. }
  379. game.state.start('map');
  380. }
  381. }
  382. },
  383. func_updateCounter: function() {
  384. totalTime++;
  385. },
  386. func_overSquare: function(){
  387. if(!clicked){
  388. //on level type A
  389. if(levelType=="A"){
  390. for(let i=0;i<floorCount;i++){
  391. if(i<=this.indice){
  392. floorBlocks.children[i].alpha = 1;
  393. }else{
  394. floorBlocks.children[i].alpha = 0.5;
  395. }
  396. }
  397. floorIndex = this.indice;
  398. //on level type B
  399. }else if(levelType=="B"){
  400. for(let i=0;i<numBlocks;i++){
  401. if(i<=this.indice){
  402. blocks.children[i].alpha = 0.5;
  403. }else{
  404. blocks.children[i].alpha = 0.2;
  405. }
  406. }
  407. blockIndex = this.indice;
  408. }
  409. }
  410. },
  411. func_outSquare: function(){
  412. if(!clicked){
  413. //on level type A
  414. if(levelType=="A"){
  415. for(let i=0;i<floorCount;i++){
  416. floorBlocks.children[i].alpha = 0.5;
  417. }
  418. floorIndex = -1;
  419. //on level type B
  420. }else if(levelType=="B"){
  421. for(let i=0;i<numBlocks;i++){
  422. blocks.children[i].alpha = 0.5;
  423. }
  424. blockIndex = -1;
  425. }
  426. }
  427. },
  428. func_clickSquare: function(){
  429. if(!clicked && !move){
  430. //on level type A
  431. if(levelType=='A'){
  432. arrow.alpha = 1;
  433. clicked = true;
  434. animate = true;
  435. if(audioStatus){
  436. beepSound.play();
  437. }
  438. tractor.animations.play('right', 5, true);
  439. if(levelLabel){ //Hiding labels
  440. blockLabel.visible = false;
  441. blockSeparator.visible = false;
  442. }
  443. //cleaning path
  444. if(levelOperator=='Minus'){
  445. for(let i=0; i< floorCount; i++){
  446. if(i>floorIndex){
  447. floorBlocks.children[i].alpha = 0;
  448. }
  449. }
  450. }else{
  451. for(let i=0; i< floorCount; i++){
  452. if(i>floorIndex){
  453. floorBlocks.children[i].alpha = 0;
  454. }
  455. }
  456. }
  457. blockIndex = numBlocks - 1;
  458. //on level type B
  459. }else if(levelType=='B'){ //Delete unselected blocks
  460. let minusBlocks = 0;
  461. for(let i=0;i<numBlocks;i++){
  462. if(i<=blockIndex){
  463. blocks.children[i].alpha = 1;
  464. }else{
  465. blocks.children[i].visible = false; //Delete unselected block
  466. minusBlocks +=1; //number of blocks to reduce
  467. }
  468. }
  469. numBlocks -= minusBlocks; //Final reduced blocks
  470. arrow.alpha = 0;
  471. clicked = true;
  472. animate = true;
  473. if(audioStatus){
  474. beepSound.play();
  475. }
  476. tractor.animations.play('right', 5, true);
  477. if(levelLabel){ //Hiding labels
  478. blockLabel.visible = false;
  479. blockSeparator.visible = false;
  480. }
  481. }
  482. }
  483. },
  484. func_postScore: function (){
  485. // Get correct information about username and default language
  486. // Variables 'username' and 'lang' is define on: js/menu.js
  487. // Variable 'lang' has all the JSON content of 'assets/languages/pt_BR.json', 'lang.lang' defined in 'js/preMenu.js' (func_setLang())
  488. // TODO: nao descobri esquema para pegar 'lang' (como 'pt_BR' ou 'en_US'), 'lang' esta' com o dicinario de lingua (definido em 'assets/languages/pt_BR.json').
  489. //if (name=='') name = username; //leo the correct is 'username'
  490. // assets/languages/pt_BR.json
  491. //DEBUG Testar 'lang'
  492. /*
  493. let contact = "";
  494. if (typeof lang === 'object') {
  495. //contact = JSON.parse(lang);
  496. for (let i in lang) // will enumerate values of 'assets/languages/pt_BR.json'
  497. contact += lang[i];
  498. // Finaliza com os valores de 'assets/languages/pt_BR.json': 'CARREGANDOFraçõesSELECIONE UM JOGODificuldadeNívelSELECINAR OPERAÇÃO E DIFICULDADEBom trabalho!Tente novamente!SELECIONAR IDIOMAMENU PRINCIPALVOLTARVER
  499. // SOLUÇÃOCírculosQuadriláteroslegendaMODOCOMSEMDIGITE SEU NOMEPRONTOOláVocê deve selecionar uma porção menor que o seu tamanho totalVocê esqueceu de digitar seu nomeÁUDIO'
  500. lang_str = contact; aux = 1;
  501. }
  502. else
  503. // if (lang === 'undefined') lang_str = "pt_BR";
  504. */
  505. let abst = "numBlocks:" + numBlocks + ", valBlocks: " + detail + " blockIndex: " + blockIndex + ", floorIndex: " + floorIndex;
  506. let hr = new XMLHttpRequest();
  507. // Create some variables we need to send to our PHP file
  508. let url = "php/save.php";
  509. let vars = "s_ip=" + hip + "&s_name=" + username + "&s_lang=" + lang + "&s_game=" + levelShape + "&s_mode=" + levelType;
  510. vars += "&s_oper=" + levelOperator + "&s_leve=" + levelDifficulty + "&s_posi=" + levelPosition + "&s_resu=" + result + "&s_time=" + totalTime + "&s_deta=" + abst;
  511. //D alert('/js/squareOne.js: url=' + url + '; aux=' + aux + ', lang_str=' + lang_str + ', lang=' + lang); // + ', this.lang=" + this.lang
  512. //D /js/squareOne.js: url=php/save.php; aux=1, lang_str=CARREGANDOFraçõesSELECIONE UM JOGODificuldadeNívelSELECINAR OPERAÇÃO E DIFICULDADEBom trabalho!Tente novamente!SELECIONAR IDIOMAMENU PRINCIPALVOLTARVER
  513. //D SOLUÇÃOCírculosQuadriláteroslegendaMODOCOMSEMDIGITE SEU NOMEPRONTOOláVocê deve selecionar uma porção menor que o seu tamanho totalVocê esqueceu de digitar seu nomeÁUDIO, lang=[object Object]
  514. // Sobre nome do usuario:
  515. // * js/squareOne.js: name
  516. // * js/pt_BR.json: welcome="Ola'", insert_name="DIGITE SEU NOME"
  517. // * php/save.php : $play = $_REQUEST["s_name"];
  518. // * js/preMenu.js : insert_name, game.add.text(...), username = document.getElementById("name_id").value;
  519. // Pegar valor de PHP para JS: echo("<script language='javascript'>location.href='download.php?arquivo=$nome_arquivo&dir=$dir&id_exer=$id_exer'</script>");
  520. hr.open("POST", url, true);
  521. hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  522. hr.onreadystatechange = function() {
  523. if(debugMode) console.log(hr);
  524. if(hr.readyState == 4 && hr.status == 200) {
  525. let return_data = hr.responseText;
  526. if(debugMode) console.log(return_data);
  527. }
  528. }
  529. // Send the data to PHP now... and wait for response to update the status div
  530. hr.send(vars); // Actually execute the request
  531. if(debugMode) console.log("processing...");
  532. },
  533. func_viewHelp: function(){
  534. if(!clicked){
  535. let pointer;
  536. if(levelType=='A'){
  537. pointer = game.add.image(endPosition, 490, 'pointer');
  538. }else{
  539. console.log("hey! ---> " + blocks.children[endIndex-1]);
  540. pointer = game.add.image(blocks.children[endIndex-1].x, blocks.children[endIndex-1].y-blockSize/2, 'pointer');
  541. }
  542. pointer.anchor.setTo(0.5, 0);
  543. pointer.alpha = 0.7;
  544. }
  545. }
  546. };