Google Apps Script equivalent for JS typed arrays (Uint8Array and Uint16Array) - google-apps-script

When I try to run the following code in google apps script
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = new Uint8Array(numArray);
...I get:
ReferenceError: "Uint8Array" is not defined.
At the same time
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = new Array(numArray);
...works just fine. Is there a clever workaround way to implement a Uint8Array in google apps script?

OK, so thanks to the comment from #Xepoch, here is the answer to my original question.
The equivalent to
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = new Uint8Array(numArray);
is (in the absence of Uint8Array):
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = [];
for(var i=0;i<numArray .length;i++) {
typedArray.push(numArray [i]<0?numArray [i]+256:numArray [i]);
}

Related

How to use Service Worker WebPush in Puppeteer headless mode?

I've trying to register service worker web push in puppetter headless mode, here is my code
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch({
// headless: false,
args: [
'--user-data-dir=/tmp/chrome',
'--enable-features=NetworkService,NetworkServiceInProcess,'
],
ignoreHTTPSErrors: true,
});
const page = await browser.newPage();
const domain = 'http://127.0.0.1:3000'
await page.goto(domain);
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
const token = await page.evaluate(async () => {
return await window.navigator.serviceWorker.ready.then(async (serviceWorkerRegistration) => {
// return serviceWorkerRegistration.pushManager.getSubscription()
const registration = await navigator.serviceWorker.getRegistration();
console.log(`getRegistration: ${registration}`);
try {
const subscription = await serviceWorkerRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: new Uint8Array([4, 94, 104, 18, 141, 49, 13, 74, 96, 202, 82, 131, 78, 91, 29, 242, 150, 102, 197, 0, 53, 149, 230, 8, 54, 38, 62, 173, 43, 28, 89, 130, 191, 222, 213, 128, 147, 62, 21, 49, 187, 95, 212, 194, 196, 253, 140, 157, 234, 34, 8, 234, 143, 158, 221, 15, 83, 8, 222, 111, 100, 204, 213, 48, 75]),
});
return subscription.toJSON()
} catch (error) {
console.log(`error: ${error}`);
return null
}
})
}).catch(e => {});
console.log(`token: ${JSON.stringify(token)}`);
})();
in non-headless mode, the code is run pretty well
PAGE LOG: getRegistration: [object ServiceWorkerRegistration]
PAGE LOG: JSHandle#object
token: {"endpoint":"https://fcm.googleapis.com/fcm/send/fBqzufyQyzU:APA91bH1kHiKTzciB6KF7GqL4zV5yfeKLnlhAvyZLHRsVcStfqh7nZYbaJ7M0p6eFx24b38v-nFKy4FYFFDJtPiAgTAiaEErQ_2la9Y7S33Ok6J8rCCio5T_gK-wf8QxeF-J87Pjff_N","expirationTime":null,"keys":{"p256dh":"BGjLgRDRBlGcv9HXyg18T-4BQyKErKnzcFJhSNTziBpVHIeuBeNUiIXNjMFBKyQP6oNz9adL3wYBAIPzW106aAY","auth":"nRQCYhw96EOFMKVqoQlp-Q"}}
but if use headless: true, the puppeteer will got a error
PAGE LOG: getRegistration: [object ServiceWorkerRegistration]
PAGE LOG: error: AbortError: Registration failed - push service not available
token: null
how could i solve this problem ?
use Service Worker WebPush in Puppeteer headless mode

How to embed a google chart (a html file) into a html webpage in adaptive width and height

I just learned to use google chart api to draw chart as follows:
Demo chart
The chart is now an html file named "demo_chart.html" whose code is:
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript", charset="utf-8">
google.charts.load("current", {packages:["corechart"]});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number','Annual Compensation');
data.addColumn('number','count');
data.addColumn({type:"string",role:"tooltip", 'p':{'html': true}});
var a = [[10, 1, '0.3%'], [12, 2, '0.9%'], [14, 2, '1.6%'], [16, 4, '2.8%'], [18, 5, '4.3%'], [20, 14, '8.7%'], [22, 22, '15.5%'], [24, 40, '28.0%'], [26, 15, '32.6%'], [28, 28, '41.3%'], [30, 26, '49.4%'], [32, 22, '56.2%'], [34, 15, '60.9%'], [36, 17, '66.1%'], [38, 9, '68.9%'], [40, 17, '74.2%'], [42, 5, '75.8%'], [44, 14, '80.1%'], [46, 7, '82.3%'], [48, 3, '83.2%'], [50, 16, '88.2%'], [52, 6, '90.1%'], [54, 4, '91.3%'], [56, 3, '92.2%'], [58, 1, '92.5%'], [60, 3, '93.5%'], [62, 6, '95.3%'], [64, 2, '96.0%'], [66, 0, '96.0%'], [68, 1, '96.3%'], [70, 2, '96.9%'], [72, 1, '97.2%'], [74, 0, '97.2%'], [76, 0, '97.2%'], [78, 0, '97.2%'], [80, 1, '97.5%'], [82, 0, '97.5%'], [84, 1, '97.8%'], [86, 0, '97.8%'], [88, 0, '97.8%'], [90, 1, '98.1%'], [92, 0, '98.1%'], [94, 0, '98.1%'], [96, 0, '98.1%'], [98, 0, '98.1%'], [100, 1, '98.4%'], [102, 0, '98.4%'], [104, 0, '98.4%'], [106, 0, '98.4%'], [108, 0, '98.4%'], [110, 2, '99.1%'], [112, 0, '99.1%'], [114, 0, '99.1%'], [116, 0, '99.1%'], [118, 0, '99.1%'], [120, 1, '99.4%'], [122, 0, '99.4%'], [124, 0, '99.4%'], [126, 0, '99.4%'], [128, 0, '99.4%'], [130, 0, '99.4%'], [132, 0, '99.4%'], [134, 0, '99.4%'], [136, 0, '99.4%'], [138, 0, '99.4%'], [140, 1, '99.7%'], [142, 0, '99.7%'], [144, 0, '99.7%'], [146, 0, '99.7%'], [148, 0, '99.7%'], [150, 1, '100.0%']];
var b = HTML_format(a);
data.addRows(b);
var options = {
title: 'Demo Column Chart',
legend: { position: 'none' },
tooltip: {isHtml: true}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
function HTML_format(a)
{
var b = [];
var scale = a[1][0] - a[0][0];
for(var i=0; i<a.length; i++)
{
var text;
if(i < a.length - 1)
{
text = "demo";
}
else
{
text = "demo";
}
b.push([a[i][0], a[i][1], text]);
}
return b;
}
</script>
</head>
<body>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
I want to embed the chart into another webpage and used iframe:
<tbody><tr><td class ='x text-center' style='align-items:center'><iframe src='demo_chart.html' style='width:900px;height:500px; border:0;max-width:100%' scrolling='no'></iframe></td><td class ='y' style=''><iframe src='demo_chart.html' style='width:900px;height:500px; border:0; max-width:100% ' scrolling='no'></iframe></td></tr></tbody>
It works well in my desktop but looks ugly in the mobile:
mobile_chart.
Could anyone help me to figure out how to correctly embed the html file so that it could be appropriately shown regardless of the width?
your problem seems to be that there is something wrong with your visualization options. You need to set the chartArea property to left:0 in your options.
After messing around with the properties I came up with these options: chartArea: {left: 0,top: 25}
so your options should look like:
var options =
{
title: 'Demo Column Chart',
legend: { position: 'none' },
tooltip: {isHtml: true},
chartArea: {left: 0,top: 25}
};
I would also suggest adding margin: auto; to your chart div to add the white space left on the main file:
<div id="chart_div" style="width: 900px; height: 500px;margin: auto;"></div>
so your demo_chart.html file should look something like this:
demo_chart.html
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript", charset="utf-8">
google.charts.load("current", {packages:["corechart"]});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number','Annual Compensation');
data.addColumn('number','count');
data.addColumn({type:"string",role:"tooltip", 'p':{'html': true}});
var a = [[10, 1, '0.3%'], [12, 2, '0.9%'], [14, 2, '1.6%'], [16, 4, '2.8%'], [18, 5, '4.3%'], [20, 14, '8.7%'], [22, 22, '15.5%'], [24, 40, '28.0%'], [26, 15, '32.6%'], [28, 28, '41.3%'], [30, 26, '49.4%'], [32, 22, '56.2%'], [34, 15, '60.9%'], [36, 17, '66.1%'], [38, 9, '68.9%'], [40, 17, '74.2%'], [42, 5, '75.8%'], [44, 14, '80.1%'], [46, 7, '82.3%'], [48, 3, '83.2%'], [50, 16, '88.2%'], [52, 6, '90.1%'], [54, 4, '91.3%'], [56, 3, '92.2%'], [58, 1, '92.5%'], [60, 3, '93.5%'], [62, 6, '95.3%'], [64, 2, '96.0%'], [66, 0, '96.0%'], [68, 1, '96.3%'], [70, 2, '96.9%'], [72, 1, '97.2%'], [74, 0, '97.2%'], [76, 0, '97.2%'], [78, 0, '97.2%'], [80, 1, '97.5%'], [82, 0, '97.5%'], [84, 1, '97.8%'], [86, 0, '97.8%'], [88, 0, '97.8%'], [90, 1, '98.1%'], [92, 0, '98.1%'], [94, 0, '98.1%'], [96, 0, '98.1%'], [98, 0, '98.1%'], [100, 1, '98.4%'], [102, 0, '98.4%'], [104, 0, '98.4%'], [106, 0, '98.4%'], [108, 0, '98.4%'], [110, 2, '99.1%'], [112, 0, '99.1%'], [114, 0, '99.1%'], [116, 0, '99.1%'], [118, 0, '99.1%'], [120, 1, '99.4%'], [122, 0, '99.4%'], [124, 0, '99.4%'], [126, 0, '99.4%'], [128, 0, '99.4%'], [130, 0, '99.4%'], [132, 0, '99.4%'], [134, 0, '99.4%'], [136, 0, '99.4%'], [138, 0, '99.4%'], [140, 1, '99.7%'], [142, 0, '99.7%'], [144, 0, '99.7%'], [146, 0, '99.7%'], [148, 0, '99.7%'], [150, 1, '100.0%']];
var b = HTML_format(a);
data.addRows(b);
var options = {
title: 'Demo Column Chart',
legend: { position: 'none' },
tooltip: {isHtml: true},
chartArea: {left: 0,top: 25}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
function HTML_format(a)
{
var b = [];
var scale = a[1][0] - a[0][0];
for(var i=0; i<a.length; i++)
{
var text;
if(i < a.length - 1)
{
text = "demo";
}
else
{
text = "demo";
}
b.push([a[i][0], a[i][1], text]);
}
return b;
}
</script>
</head>
<body>
<div id="chart_div" style="width: 900px; height: 500px;margin: auto;"></div>
</body>
</html>
This should fix your problem.

How to decode a Gzip Http Response in Flutter?

I am new to Flutter. I am making a Network Request and I am getting the correct response, but the data is Gzipped. I have decompressed the same in Swift, but with Flutter, I am unable to do that. Can anyone please help?
Here's what I have tried:
import 'dart:convert';
import 'package:http/http.dart';
import 'package:archive/archive.dart';
import 'package:flutter_app/Constants/constants.dart';
class ServiceHelper {
static final sharedInstance = ServiceHelper();
Future<Response> sendRequest({String path, Map<String,dynamic> params}) async {
final String url = Constants.testURL+path;
var body = jsonEncode(params);
Response response = await post(url, body:body);
final gZipped_data = GZipDecoder().decodeBytes(response.bodyBytes);
print(gZipped_data); //flutter: [123, 34, 115, 116, 97, 116, 117, 115, 34, 58, 50, 48, 48, 44, 34, 109, 101, 115, 115, 97, 103, 101, 34, 58, 34, 83, 105, 103, 110, 32, 105, 110, 32, 67, 111, 109, 112, 108, 101, 116, 101, 100, 32, 83, 117, 99, 99, 101, 115, 115, 102, 117, 108, 108, 121, 34, 44, 34, 100, 97, 116, 97, 34, 58, 123, 34, 117, 115, 101, 114, 95, 105, 110, 102, 111, 34, 58, 123, 34, 112, 108, 97, 121, 101, 114, 95, 105, 100, 34, 58, 49, 52, 56, 54, 57, 44, 34, 112, 108, 95, 97, 112, 112, 95, 105, 100, 34, 58, 34, 57, 90, 104, 57, 82, 66, 108, 70, 34, 44, 34, 112, 114, 111, 102, 105, 108, 101, 95, 112, 105, 99, 34, 58, 34, 104, 116, 116, 112, 115, 58, 92, 47, 92, 47, 119, 119, 119, 46, 115, 112, 111, 114, 116, 115, 113, 119, 105, 122, 122, 46, 99, 111, 109, 92, 47, 118, 51, 92, 47, 105, 109, 103, 92, 47, 112, 108, 97, 121, 101, 114, 115, 92, 47, 112, 105, 99, 92, 47, 105, 80, 45, 49, 53, 50, 51, 56, 54, 57, 50, 57, 56, 46, 112, 110, 103, 34, 44, 34, 101, 109, 97, 105, 108, 34, 58, 34, 116, 101, 99, 104, 121, <…>
//This throws an error: Unhandled Exception: FormatException: Bad UTF-8 encoding 0x8b (at offset 1)
return response;
}
}
//This is the login function and it is in a different file main.dart
Future<void> login(
{String email,
String name,
int source,
String sourceStr,
String picString,
String idToken}) async {
final String playerID = '';
final String token = await getIOSToken().then((token){
return token;
});
Map<String, dynamic> params = {
"email": email,
"name": name,
"player_id": playerID,
"source_id": source,
"profile_pic": picString,
"password": passwordController.text ?? "",
"ios_token":token,
"device_type": "I",
"language_iso": "en",
"referred_by": "loginDefault",
"firebase_id_token": idToken,
"app_version": "4.4.9"
};
Response response = await ServiceHelper.sharedInstance
.sendRequest(path: Constants.login, params: params);
if (response.statusCode == 201) {
// If server returns an OK response, parse the JSON.
return UserDetails.fromJson(json.decode(response.body));
} else {
// If that response was not OK, throw an error.
throw Exception('Failed to load post');
}
}
The expected response is JSON, but as it is Gzipped and I am unable to decompress it, I do not know how to get the JSON from it. I have tried decoding it and it gives me gzipped_data as a List of Integers as you can see above. How can I get the JSON from it?
I'm using GZipCodec from dart:io.
Try it like this to return the response as a String.
Future<String> sendRequest({String path, Map<String,dynamic> params}) async {
final String url = Constants.testURL+path;
var body = jsonEncode(params);
Response response = await post(url, body:body);
final decoded_data = GZipCodec().decode(response.bodyBytes);
return utf8.decode(decoded_data, allowMalformed: true);
}
The body of a response will be automatically uncompressed.
Visit https://api.flutter.dev/flutter/dart-io/HttpClient/autoUncompress.html

Draw line chart using shapes in adobe flex

I want to draw line chart for ECG reading using Shapes component. I want graph exactly like this image.
i finished 90% code. but when i call clear() means all lines cleared.
i want to give some space between two different reading.
My code:
<fx:Script>
<![CDATA[
private var arrSPO2:Array = [33, 35, 36, 33, 28, 21,35, 36, 33, 28, 21, 13, 6,33, 28, 21, 13, 6, 0, 0, 0,28, 21, 13, 6, 0, 0, 0, 0, 0, 10,28, 21, 13, 6, 0, 0, 0, 0, 0, 10, 31, 56, 78,13, 6, 0, 0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94,6, 0, 0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55,0, 0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41,0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44,0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32,0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7,0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0, 0,10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0, 0, 0, 2, 19,31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0, 0, 0, 2, 19, 43, 68, 90,56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0];
private var oldX:int = 0;
private var oldY:int = 0;
private var newX:int = 0;
private var newY:int = 0;
private static const TIMER_INTERVAL:int = 50;
private var timer:Timer = new Timer(TIMER_INTERVAL);
private var shapesSPO2:Shape = new Shape();
[Bindable] private var index:int = -1;
protected function init():void {
}
private function timerHandler(event:TimerEvent):void {
trace(timer.currentCount);
index = timer.currentCount - 1;
//draw SPO2
newX += 2;
newY = ((arrSPO2[index] * -1) / 2 + 120);
if (oldY == 0) {
oldY = newY;
}
shapesSPO2.graphics.moveTo(oldX, oldY);
shapesSPO2.graphics.lineTo(newX, newY);
ui1.addChild(shapesSPO2);
oldX = newX;
oldY = newY;
if (index > arrSPO2.length) {
shapesSPO2.graphics.clear();
shapesSPO2.graphics.lineStyle(2, 0x990000, .75);
oldX = newX = 0;
timer.reset();
timer.start();
}
}
protected function btnSPO2_clickHandler(event:MouseEvent):void {
oldX = newX = 0;
shapesSPO2.graphics.lineStyle(2, 0x990000, .75);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.reset();
timer.start();
}
]]>
</fx:Script>
<s:VGroup width="100%" height="100%"
horizontalAlign="center" verticalAlign="middle">
<mx:HBox width="550" height="500"
borderColor="#000000" borderVisible="true" borderStyle="solid" borderAlpha="0.2"
visible="true" includeInLayout="true">
<s:VGroup id="vgGraph" width="100%" height="100%"
horizontalAlign="center"
gap="10"
padding="10">
<s:HGroup width="100%">
<s:Label text="Current Index : {index}" fontSize="16"
fontWeight="bold" />
</s:HGroup>
<mx:UIComponent id="ui1" width="100%" height="100%" />
<!--<s:SpriteVisualElement id="spriteVis" width="100%" height="100%" />-->
<s:Button id="btnSPO2" label="Draw SPO2 Graph" click="btnSPO2_clickHandler(event)" />
</s:VGroup>
</mx:HBox>
</s:VGroup>
To do that you can change your code like this :
private const margin:int = 10;
private function timerHandler(event:TimerEvent):void {
if (index == arrSPO2.length - 1) {
// set the margin between the last chart and the new one
newX = newX + margin;
oldX = newX;
// reset index
index = 0;
timer.reset();
timer.start();
// exit if we have reached the last element of our array
return;
}
index = timer.currentCount - 1;
newX += 2;
newY = ((arrSPO2[index] * -1) / 2 + 120);
if (oldY == 0) {
oldY = newY;
}
shapesSPO2.graphics.moveTo(oldX, oldY);
shapesSPO2.graphics.lineTo(newX, newY);
ui1.addChild(shapesSPO2);
oldX = newX;
oldY = newY;
}
Which will give you something like this :
Hope that can help.
I've modified your timerHandler as below:
private function timerHandler(event:TimerEvent):void {
trace(timer.currentCount);
index = timer.currentCount - 1;
if (index > arrSPO2.length) {
//shapesSPO2.graphics.clear();
//shapesSPO2.graphics.lineStyle(2, 0x990000, .75);
newX += 10;
oldX = newX;
timer.reset();
timer.start();
return;
}
//draw SPO2
newX += 2;
if(newX > ui1.width)
{
oldX = newX = 0;
}
newY = ((arrSPO2[index] * -1) / 2 + 120);
if (oldY == 0) {
oldY = newY;
}
if(index ==0)
{
oldY = newY;
}
shapesSPO2.graphics.moveTo(oldX, oldY);
shapesSPO2.graphics.lineTo(newX, newY);
ui1.addChild(shapesSPO2);
oldX = newX;
oldY = newY;
}

Reading numeric keys from JSON file

Let's say I store a dictionary's values in JSON file. Here is the simplified code:
test = {}
for i in range(10):
for j in range(15):
test['{},{}'.format(i, j)] = i * j
with open('file1.json', 'w') as f:
json.dump(test, f)
I have hard time reading back from this file. How can I read back from this file into a dictionary with elements like key as [i,j] and value as i*j?
I use simple
with open('file1.json', 'r') as f:
data2 = json.load(f)
Do you mean something like this?
with open('file1.json', 'r') as f:
data2 = {tuple(int(x) for x in k.split(',')): v
for (k, v) in json.load(f).items()}
Your code will returns a dictionary contain unicode key and values if you want to get a dictionary contains the integer values you can use json.dumps after loading the file :
import json
test = {}
for i in range(10):
for j in range(15):
test['{},{}'.format(i, j)] = i * j
with open('file1.json', 'w') as f:
json.dump(test, f)
with open('file1.json', 'r') as f:
data2 = json.load(f)
print json.dumps(data2)
result :
{"1,8": 8, "1,9": 9, "1,6": 6, "1,7": 7, "1,4": 4, "1,5": 5, "1,2": 2, "1,3": 3, "1,0": 0, "1,1": 1, "7,6": 42, "7,7": 49, "5,8": 40, "5,9": 45, "3,8": 24, "3,9": 27, "5,2": 10, "5,3": 15, "5,0": 0, "3,7": 21, "3,0": 0, "5,7": 35, "3,2": 6, "3,3": 9, "3,14": 42, "3,12": 36, "3,13": 39, "3,10": 30, "3,11": 33, "2,8": 16, "5,14": 70, "5,10": 50, "5,11": 55, "5,12": 60, "5,13": 65, "0,8": 0, "4,8": 32, "0,13": 0, "0,12": 0, "0,11": 0, "0,10": 0, "0,14": 0, "6,9": 54, "6,8": 48, "6,1": 6, "6,0": 0, "6,3": 18, "6,2": 12, "6,5": 30, "6,4": 24, "6,7": 42, "6,6": 36, "6,14": 84, "6,11": 66, "6,10": 60, "6,13": 78, "6,12": 72, "8,9": 72, "8,8": 64, "8,7": 56, "8,6": 48, "8,5": 40, "8,4": 32, "8,3": 24, "8,2": 16, "8,1": 8, "8,0": 0, "5,1": 5, "2,13": 26, "3,4": 12, "3,5": 15, "3,6": 18, "0,7": 0, "0,6": 0, "0,5": 0, "0,4": 0, "0,3": 0, "0,2": 0, "0,1": 0, "0,0": 0, "5,6": 30, "0,9": 0, "3,1": 3, "1,10": 10, "1,11": 11, "1,12": 12, "1,13": 13, "2,9": 18, "5,4": 20, "2,5": 10, "2,4": 8, "2,7": 14, "2,6": 12, "2,1": 2, "2,0": 0, "2,3": 6, "2,2": 4, "4,3": 12, "4,2": 8, "4,1": 4, "4,0": 0, "4,7": 28, "4,6": 24, "4,5": 20, "4,4": 16, "2,11": 22, "2,10": 20, "4,9": 36, "2,12": 24, "2,14": 28, "1,14": 14, "5,5": 25, "8,13": 104, "8,12": 96, "8,11": 88, "8,10": 80, "8,14": 112, "7,12": 84, "7,13": 91, "7,10": 70, "7,11": 77, "7,14": 98, "4,14": 56, "4,13": 52, "4,12": 48, "4,11": 44, "4,10": 40, "7,8": 56, "7,9": 63, "9,4": 36, "9,5": 45, "9,2": 18, "9,3": 27, "9,0": 0, "9,1": 9, "7,0": 0, "7,1": 7, "7,2": 14, "7,3": 21, "7,4": 28, "7,5": 35, "9,8": 72, "9,9": 81, "9,6": 54, "9,7": 63, "9,10": 90, "9,11": 99, "9,12": 108, "9,13": 117, "9,14": 126}