Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


lynkfs last won the day on January 15

lynkfs had the most liked content!

About lynkfs

  • Rank

Profile Information

  • Gender
  • Location

Recent Profile Visitors

683 profile views
  1. lynkfs

    Renaming form in ObjectInspector

    Looking at @IgorSavkic's argument to be able to have different form class names and unit names, I agree with him. We all have different styles and the IDE should accommodate that (so only the project manager should change unit/file names)
  2. lynkfs

    Renaming form in ObjectInspector

    This behaviour is not limited to Forms but to other classes as well For example: Looking at the 'unit structure' tab with the SmartCL.Borders unit open, I can rename the TW3Border class to something else For Forms I don't see any advantage of changing a form class and not change the unit and filename, but for other object classes changing the class name only is somewhat handy (although a search and replace old/new classname will have the same effect)
  3. lynkfs

    Send an email ?

    yep (works @ my place)
  4. lynkfs

    Send an email ?

    This api doesn't allow local execution (file:///C:/Users/.../www/index.html) but requires a http(s) based url (https://.../www/index.html) so index.html / index.js needs to be server-side
  5. lynkfs

    Send an email ?

    I checked, runs perfectly well server-side (but not client-side)
  6. lynkfs

    Quantum computing with Smart

    Is it possible to do a bit of quantum computing using SMS ? The answer looks to be yes, using IBM's quantum computer resources which are partly made available for developers Basics first : IBM has released it's SDK to program these quantum computers using a visual composer, Python, a proprietary assembler QASM format and some run and execute utilities. There is however a second way of using its quantum resources, using the entry-points of is Q-experience REST server. Most if not all of the visual composer functions can be done by ajax-calls ! To demonstrate : the first thing is to acquire an api-token. (Create an account on https://quantumexperience.ng.bluemix.net/qx/experience. Log in and navigate to the Composer. Username > My Account, and then Advanced on the upper right. Then generate API Token. Api Tokens are personal and are not supposed to be shared.) The next thing is to generate a session token (access token). This can be done in code. This screenshot shows a couple of these REST server calls and its results : The first button (get access) generates a session token The second button queries which quantum computers are available, how many qubits can be used, if it is online and what type of system it is. Current results show 3 quantum systems - 2 real ones and 1 simulator The third button (current Temp) gives some processor info of the selected system. In this case the current temperature in Kelvin : the Melbourne processor is cooled to just above the absolute minimum. Next : the next button to implement will be to submit some code to one of the available processors for processing. Below is the project code for these REST calls unit Form1; interface uses System.Types, System.Types.Convert, System.Objects, System.Time, SmartCL.System, SmartCL.Time, SmartCL.Graphics, SmartCL.Components, SmartCL.FileUtils, SmartCL.Forms, SmartCL.Fonts, SmartCL.Theme, SmartCL.Borders, SmartCL.Application, SmartCL.Net.Http, ECMA.Json, SmartCL.Controls.Button, SmartCL.Controls.Label, HTMLTableElement, SmartCL.Controls.ScrollBox, SmartCL.Controls.Panel, SmartCL.Controls.ComboBox; type TForm1 = class(TW3Form) procedure W3Button3Click(Sender: TObject); procedure W3Button2Click(Sender: TObject); procedure W3Button1Click(Sender: TObject); private {$I 'Form1:intf'} protected procedure InitializeForm; override; procedure InitializeObject; override; procedure Resize; override; DBRows : integer := 0; FHttp : TW3HttpRequest; smscursor: variant; procedure GetAccessToken(Sender: TW3HttpRequest); procedure ListAvailableSystems(Sender: TW3HttpRequest); procedure GetTempKelvin(Sender: TW3HttpRequest); AccessToken : string; end; implementation { TForm1 } procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components end; procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} end; { Button1 } procedure TForm1.W3Button1Click(Sender: TObject); begin //Get Access Token var FHttp := TW3HttpRequest.Create; FHttp.OnDataReady := GetAccessToken; FHttp.open("POST",'https://quantumexperience.ng.bluemix.net/api/users/loginWithToken'); FHttp.RequestHeaders.Add("Content-type","application/json"); var api : variant := new JObject; api.apiToken := TString.encodeURIComponent('a59d26ebf........1d6d6d4a28c430b5336aba'); FHttp.send(json.stringify(api)); end; procedure TForm1.GetAccessToken(Sender: TW3HttpRequest); begin smscursor := JSON.parse(Sender.ResponseText); AccessToken := smscursor.id; W3Label1.Caption:= 'Access Token : ' + AccessToken; end; { Button2 } procedure TForm1.W3Button2Click(Sender: TObject); begin //List available Q systems var FHttp := TW3HttpRequest.Create; FHttp.OnDataReady := ListAvailableSystems; FHttp.open("GET",'https://quantumexperience.ng.bluemix.net/api/Backends?access_token=' + AccessToken); FHttp.RequestHeaders.Add("Content-type","application/json"); FHttp.send; end; procedure TForm1.ListAvailableSystems(Sender: TW3HttpRequest); begin var W3TableElement1 : TW3TableElement := TW3TableElement.Create(W3Panel1); //add 5 columns to the grid W3TableElement1.AddColumn('Name',200); //title, width W3TableElement1.AddColumn('Description',200); W3TableElement1.AddColumn('Qubits',50); W3TableElement1.AddColumn('System type',150); W3TableElement1.AddColumn('Status',50); smscursor := JSON.parse(Sender.ResponseText); W3ComboBox1.Clear; for var i := 0 to smscursor.length -1 do begin W3TableElement1.AddCell(i+1,1,smscursor[i].name); W3TableElement1.AddCell(i+1,2,smscursor[i].description); W3TableElement1.AddCell(i+1,3,smscursor[i].nQubits); if smscursor[i].simulator = true then W3TableElement1.AddCell(i+1,4,'quantum simulator') else W3TableElement1.AddCell(i+1,4,'quantum system'); W3TableElement1.AddCell(i+1,5,smscursor[i].status); W3ComboBox1.add(smscursor[i].name); end; W3Panel1.NativeScrolling := true; W3ComboBox1.OnChanged := procedure (Sender: TObject) begin writeln(W3ComboBox1.Items[W3ComboBox1.SelectedIndex]); end; end; { Button3 } procedure TForm1.W3Button3Click(Sender: TObject); begin //Get Temp var FHttp := TW3HttpRequest.Create; FHttp.OnDataReady := GetTempKelvin; //'https://quantumexperience.ng.bluemix.net/api/Backends/NAME/parameters?access_token=ACCESS-TOKEN'; FHttp.open("GET",'https://quantumexperience.ng.bluemix.net/api/Backends/' + W3ComboBox1.Items[W3ComboBox1.SelectedIndex] + '/parameters?access_token=' + AccessToken); FHttp.RequestHeaders.Add("Content-type","application/json"); FHttp.send; end; procedure TForm1.GetTempKelvin(Sender: TW3HttpRequest); begin If Sender.ResponseText = '{}' then begin W3Label3.Caption := 'Simulators are not cooled to (close to) absolute minimum'; end else begin smscursor := JSON.parse(Sender.ResponseText); if smscursor.fridgeParameters.Temperature.value = '' then W3Label3.Caption := 'Processor does not support Temp reading' else W3Label3.Caption:= 'Current Temp : ' + smscursor.fridgeParameters.Temperature.value + ' Kelvin'; end; end; procedure TForm1.Resize; begin inherited; end; initialization Forms.RegisterForm({$I %FILE%}, TForm1); end. In the end hopefully it will be possible to recreate the classic Battleships game using quantum computing, as described here
  7. lynkfs

    Send an email ?

    if it runs fine by deleting part of code, by all means it may be that Google has tweaked the gmail api (client or auth2 library) slightly in the last couple of months
  8. lynkfs

    table grid

    the simplest of grids, based on the html <table> element usage var W3TableElement1 : TW3TableElement := TW3TableElement.Create(W3Panel1); //add 4 columns to the grid W3TableElement1.AddColumn('Name',200); //title, width W3TableElement1.AddColumn('Description',200); W3TableElement1.AddColumn('Type',150); W3TableElement1.AddColumn('Status',50); for var i := 0 to 2 do begin W3TableElement1.AddCell(i+1,1,'Name-'+inttostr(i)); //row,column,text W3TableElement1.AddCell(i+1,2,'Desc-'+inttostr(i)); W3TableElement1.AddCell(i+1,3,'Type-'+inttostr(i)); W3TableElement1.AddCell(i+1,4,'Stat-'+inttostr(i)); end; W3Panel1.NativeScrolling := true; component unit HTMLTableElement; interface uses SmartCL.System, System.Types, SmartCL.Components; type TW3TableElement = class(TW3CustomControl) protected function MakeElementTagObj : THandle; override; TableRow : Variant; public procedure AddColumn(title: string; colwidth: integer); procedure AddCell(row, column: integer; cell: String); ColumnCount : integer := 0; RowCount : integer := 0; end; implementation { TW3TableElement } function TW3TableElement.MakeElementTagObj : THandle; begin Result := w3_createHtmlElement('table'); end; procedure TW3TableElement.AddColumn(title: string; colwidth: integer); begin // Inc(ColumnCount); //when inserting the first column, do a rowInsert for the column titles If ColumnCount = 1 then begin TableRow := handle.insertRow(0); Inc(RowCount); end; // Insert a cell in the row at index [column] var newCell = TableRow.insertCell(columnCount-1); newCell.setAttribute('bgColor','lightgrey'); newCell.setAttribute('width',inttostr(colwidth)+'px'); // Append a text node to the cell var newText = browserapi.document.createTextNode(title); newCell.appendChild(newText); end; procedure TW3TableElement.AddCell(row, column: integer; cell: String); begin // //when inserting the first cell in a row, do a rowInsert If Column = 1 then begin TableRow := handle.insertRow(RowCount); Inc(RowCount); end; // Insert a cell in the row at index [column] var newCell = TableRow.insertCell(column-1); // Append a text node to the cell var newText = browserapi.document.createTextNode(cell); newCell.appendChild(newText); end; end. note : this is an upgraded unit as referred to in this post - method 1
  9. lynkfs

    NodeJS file utils and native app

    yes to a node server with a back-end mysql db, no to a node server accessing the native file system I have these links on my system : node socket server with mysql db https://forums.smartmobilestudio.com/topic/4652-node-ground-zero/?tab=comments#comment-23125 file enumeration https://jonlennartaasenden.wordpress.com/?s=node.js I've done some conversions using nativefier, works ok I'm racking my brains what the name is of this other native library I've used once, but it eludes me at present
  10. lynkfs

    Working with Emoji data

  11. lynkfs

    serviceWorkers (fetch)

    Technically the cacheStorage api is not that hard, but choosing and implementing the different scenario's (cache-first-then-network, network-first-then-cache etc etc) becomes a bit tedious. And then there is the old browser caching mechanism too, which doesn't go away - two different caching mechanisms to take care of. There is a caching cookbook below (and some other links I collected for myself) difference between webworkers and service workers https://www.quora.com/Whats-the-difference-between-service-workers-and-web-workers-in-JavaScript https://stackoverflow.com/questions/38632723/what-can-service-workers-do-that-web-workers-cannot using serviceWorkers https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers https://itnext.io/service-workers-your-first-step-towards-progressive-web-apps-pwa-e4e11d1a2e85 https://developers.google.com/web/fundamentals/primers/service-workers/ inline webworker file https://forums.smartmobilestudio.com/topic/4662-compiled-procedures/?tab=comments#comment-23272 URL.createObjectURL not for serviceWorkers https://www.chromestatus.com/feature/5685092332601344 https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL https://github.com/w3c/ServiceWorker/issues/688 Failed to register a ServiceWorker: The URL protocol of the script ('blob:http%3A//') is not supported. workertest : test your browser https://html5workertest.com/ cookbook https://serviceworke.rs/ google https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/ (problems : yahoos weather service is deprecated as per jan 2019 - converting it to OpenWeatherMap sourcecode insists unnecessarily on installing everything in server root - changed urls of resources to relative)
  12. lynkfs


    Like this a lot. Both your first link and the examples in the unit above. I've been fairly happy with 'pascalising' vanilla js promises till now, but this approach 'promises' something better.
  13. lynkfs


    a simple promise in vanilla javascript looks something like this var promise1 = new Promise(function(resolve, reject) { setTimeout(function() { resolve('foo'); }, 300); }); promise1.then(function(value) { console.log(value); // expected output: "foo" }); console.log(promise1); // expected output: [object Promise] Using the Ecma.promise unit the next code snippet does compile, but fails on execution ("reference error, PromiseInit is not defined") var Pinit := new JPromiseInit; var p := JPromise.Create(PInit); p.then(function(x:variant):variant begin result := x; end); Googling 'PromiseInit' or "_Promise" only gives a handful of vague (and dated) references Nonplussed
  14. lynkfs


    Does anyone know how to use the Ecma.Promise unit ? Looks like the external PromiseInit ref doesn't exist
  15. lynkfs

    serviceWorkers (fetch)

    WebWorkers are a way of off-loading tasks from the main browser into a separate thread. ServiceWorkers sit between the browser and the network and extend these capabilities by a couple of powerful features : offline detection and interception possibilities of network requests (fetch api) resource caching under program control (new cacheStorage api) background syncing saving browser apps as icons on the homescreen serving push notifications ServiceWorkers are integral to Progressive Web Apps Architecturally a serviceWorker is just a separate js file, which means that 2 Smart projects are needed (one for the main program, one for the serviceWorker). For normal webWorkers there is a workaround in that it is possible to generate an in-memory js-file using the blob: protocol (see forum post here), so the webWorker can be generated from the main program. For serviceWorkers this approach should work as well, however all modern browsers have closed this avenue (see here, here and here). Not sure if this is temporary or permanent. ServiceWorkers are created in the main program, a bit differently then normal. No 'new' object constructor but instead a call to a registration function, returning a promise. var navigator external 'navigator': variant; if navigator.serviceWorker then begin navigator.serviceWorker.register('sw-v1.js') .then(procedure(registration:variant) begin console.log('Service Worker registered with scope: ', registration.scope); end) .catch(procedure(err:variant) begin console.log('Service worker registration failed: ', err); end) end; (Adding the link to the external navigator object in the first line means no asm blocks are required. The above could be wrapped up in a TServiceWorker object). 1) network request interceptions (fetch) For the serviceworker : start a new project and delete all pre-generated forms and units. Set output to js file (linker) and unclick 'use main body' in code generation. Replace contents of root-unit with var sw : variant; asm @sw = self; end; sw.addEventListener("fetch", procedure(event:variant) begin if (event.request.url.includes("res/app.css")) then begin event.respondWith( fetch("res/appmodified.css"); ) ); end end); Soon as the request to load the standard Smart resource-file 'res/app.css' is detected, it is intercepted and replaced with another resourcefile. Usually communication between worker and main is done through messaging. There is however a short-cut where the worker can modify the calling main page directly : add a Response object to the event.responseWith method with appropriate headers asm event.respondWith( new Response( "body {background: green !important;}", {headers: {"Content-Type": "text/css" }} ) ); end; this will change the backgroundcolor of the form to green. Change the Content-Type to "text/html" and the preceding string to valid html and the form will be replaced with the rendered html content. demo (click button and do refresh) and projects (main and worker)