Wednesday, December 13, 2017

React Firebase Deployments

   Some helpful hints to syntax errors, notably as related to 'npm run build' and 'firebase deploy' as related to syntax error shows either an older version a 'build/static/js/mainxxxxx.js' build or a current version but seems to be referencing an older version of this.

1.  Updating the 'index.html' file on new deployment.  Important to do this.  You can add a space in the file (or some character which makes the operation of the file functionally unchanged), for instance.

2.  In the Firebase console under the hosting tab, you may need to rollback to the current deployment, or at least ensure this has happened.  I have found that any new 'firebase deploy' command hasn't fully ensured updates of all deployment files to the latest deployment batch.

I have also experienced old cached site data remaining even upon refreshing firebase server data.  I am not certain why this seems to be more so the case either with 'firebase deploy' ments or 'firebase serve' (local hosting), but with chrome browser, you can do a refresh load with ctrl+'reload'.  Seems to remedy old data in the browser system. 

My current experience as of 12/13/2017

  

Sunday, November 5, 2017

React App recommendations for inlining svg art

Recently playing around with Adobe Illustrator in conjunction with Animate CC for export into ReactJS .  However, as I've encountered with Animate CC choppy motions for animating svg group elements coupled to all the hassle of inlining svg plus simil code...this allegedly is trending down in terms of popularity, one particular bright spot that I've found for inlining rapidly lengthy pieces of svg code comes by way of transpiling (in cli environment) an svg into reactjs components.  It is done easily at console.  Here's a link that helps doing such...

https://medium.com/@scbarrus/transform-raw-svg-files-into-react-components-in-seconds-25faf56a6f07

I've found that it does what it says in a second for large svg files.  Just follow instructions for installing globally via npm.

Of course aside from working on a component search object element and then modify inside reactjs component object for animation with loop call inside such component (in other words creating js side animation), css is an alternative as well.  React by the way is nice for creating ios and android apps while avoiding all the hassles of learning to have to code in swift and using xcode or android and java in general.  React apps can be provisioned for web apps as well. 


Friday, October 13, 2017

Angular backend integration problem...custom parser

I found any number of back end parsing solutions that didn't work with my angular app, and I spent more time researching this problem in the long run.  It took me 30 minutes (no kidding) to write a functioning string parser for approximately several hours of non solution to Angular typescript component interfacing.

Example parser

  
class ParseObject{
    toParseObj: string;
    pitems: PostItem[];
    constructor(objstr: string){
        this.toParseObj = objstr;
        this.pitems = [];
    }
    catchEscape(rs: string[]){
        var i = 0;
        var rtnrs: string[] = [];
        var setcontinue: boolean = false;
        for (let r of rs){
            if (setcontinue){
                i+=1;
                setcontinue = false;
                continue;
            }
            if (r[r.length-1] == "\\" ){
                if ((i+1) < (rs.length-1)){
                    let fr: string = rs[i+1];
                    rtnrs.push(r+fr);
                    setcontinue = true;
                }
            }
            else{
                rtnrs.push(r);
            }
            i+=1 
        }
        return rtnrs;
    }

    iterateParse(strP: string, strset: string[]){
        for (let strp in strset){
            var splitobj = strp.split(strP);
            var nsplitobj = this.catchEscape(splitobj);
        }
    }

    parseString(){
        /*{"records":[{"name":"JimBob","message":"Hello katz!"},{"name":"Dr IQ","message":"Hello hello my name is Jim Bobby.
 Been an old friend of shorty there!
 Gratz!"}]}*/
        //presumes user properly input string for formatting
        var rs = this.toParseObj.split(']}');
        console.log(rs);
        //catch escapes
        var nrs = this.catchEscape(rs);
        console.log(nrs);
        let nrs0 = nrs[0];
        var nrs1 = nrs0.split('{"records":[');
        var nrs2 = this.catchEscape(nrs1);
        console.log(nrs2);
        let nrs3 = nrs2[1];
        var nrs4 = nrs3.split("},{");
        var nrs5 = this.catchEscape(nrs4);
        console.log(nrs5);
        for (let nr of nrs5){
            //split "," for key,value s
            var nrs6 = nr.split(",");
            var nrs7 = this.catchEscape(nrs6);
            console.log(nrs7);
            let nrs8 = nrs7[0].split("\"name\":");
            let namevalue = nrs8[1].split("\"")[1];
            console.log(nrs8);
            let nrs9 = nrs7[1].split("\"message\":");
            let messagevalue = nrs9[1].split("\"")[1];
            this.pitems.push(new PostItem(namevalue,messagevalue));
        }
        return this.pitems;
    }
}
class PostItem {
    constructor(public name: string,
                public message: string) {
    }
  }

You can build a custom service to be used with a promise


Here's my component service
import { Component, Injectable, OnInit } from '@angular/core';
import {PVector} from './lineData';
import {frameResizer} from './frameResizer';
import { routerTransition } from './router.animations';
import {Guest } from './guest';
import {Http, Headers, RequestOptions, Response} from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';
/*{"records":[{"name":"JimBob","message":"Hello katz!"},{"name":"Dr IQ","message":"Hello hello my name is Jim Bobby.
 Been an old friend of shorty there!
 Gratz!"}]}*/

class ParseObject{
    toParseObj: string;
    pitems: PostItem[];
    constructor(objstr: string){
        this.toParseObj = objstr;
        this.pitems = [];
    }
    catchEscape(rs: string[]){
        var i = 0;
        var rtnrs: string[] = [];
        var setcontinue: boolean = false;
        for (let r of rs){
            if (setcontinue){
                i+=1;
                setcontinue = false;
                continue;
            }
            if (r[r.length-1] == "\\" ){
                if ((i+1) < (rs.length-1)){
                    let fr: string = rs[i+1];
                    rtnrs.push(r+fr);
                    setcontinue = true;
                }
            }
            else{
                rtnrs.push(r);
            }
            i+=1 
        }
        return rtnrs;
    }

    iterateParse(strP: string, strset: string[]){
        for (let strp in strset){
            var splitobj = strp.split(strP);
            var nsplitobj = this.catchEscape(splitobj);
        }
    }

    parseString(){
        /*{"records":[{"name":"JimBob","message":"Hello katz!"},{"name":"Dr IQ","message":"Hello hello my name is Jim Bobby.
 Been an old friend of shorty there!
 Gratz!"}]}*/
        //presumes user properly input string for formatting
        var rs = this.toParseObj.split(']}');
        console.log(rs);
        //catch escapes
        var nrs = this.catchEscape(rs);
        console.log(nrs);
        let nrs0 = nrs[0];
        var nrs1 = nrs0.split('{"records":[');
        var nrs2 = this.catchEscape(nrs1);
        console.log(nrs2);
        let nrs3 = nrs2[1];
        var nrs4 = nrs3.split("},{");
        var nrs5 = this.catchEscape(nrs4);
        console.log(nrs5);
        for (let nr of nrs5){
            //split "," for key,value s
            var nrs6 = nr.split(",");
            var nrs7 = this.catchEscape(nrs6);
            console.log(nrs7);
            let nrs8 = nrs7[0].split("\"name\":");
            let namevalue = nrs8[1].split("\"")[1];
            console.log(nrs8);
            let nrs9 = nrs7[1].split("\"message\":");
            let messagevalue = nrs9[1].split("\"")[1];
            this.pitems.push(new PostItem(namevalue,messagevalue));
        }
        return this.pitems;
    }
}
class PostItem {
    constructor(public name: string,
                public message: string) {
    }
  }

@Injectable()
export class SearchService {
  apiRoot: string = 'url/path/to/your/fetch.php';
  results: PostItem[];
  loading: boolean;

  constructor(private http: Http) {
    this.results = [];
    this.loading = false;
  }

  search() {
    let promise = new Promise((resolve, reject) => {
      let apiURL = this.apiRoot;
      
      this.http.get(apiURL)
          .toPromise()
          .then(
              res => { // Success
                console.log(res);
                var json=JSON.stringify(res);
                var jobj = JSON.parse(json);
                var jobj2 = jobj["_body"];
                //var jobj3 = JSON.parse(jobj2);
                console.log(jobj2);
                var parseobj = new ParseObject(jobj2);
                this.results = parseobj.parseString();
                this.results.reverse();
                console.log(this.results);
                
                /*
                for (let job in jobj){
                    this.results.push(new PostItem(job.name, job.message));
                }
                //this.results = res.json().results.map
                /*
                this.results = jobj.map(item => {
                  return new PostItem(
                      item.name,
                      item.message
                  );
                });*/
                // this.results = res.json().results;
                //posts = res.data.records;
                resolve();
              },
              msg => { // Error
                console.log("hit error");
                reject(msg);
              }
          );
    });
    return promise;
  }
}
Also make sure to make http global via app.module.ts and adding your service as a provider with
import { HttpModule } from '@angular/http';

...

@NgModule({
  imports: [
    ..., HttpModule
  ],
  declarations: [
   ...
  ],
 
  providers: [ SearchService ],
  ...
})

Deployment of your Angular app

You've may know the basics about instancing your Angular app via command line environment with ng serve yada yada yada, but do you know how to build bundle your app for distribution/deployment?


ng build --prod

 command will create dist (distribution folder with javascript bundles). 

Then with the generated files in the dist folder, you need simply upload to deployment (site host) and your site should be up and running.  You can google search to do deployment to AWS (amazon) or any other site hosting solution.  

Saturday, September 30, 2017

Metal Swift usage of Command Buffer with complex Kernel(s) computations and more

Advice for working with complex kernel encoding computations:

-Account for all commandBuffer instances and .commit() s its important since any added instance without a .commit on the commandBuffer in a draw loop is a memory leak.  May not show on XCode Instruments stack trace but will show on Debug Memory Graph while running in Debug mode (see https://medium.com/@xcadaverx/locating-the-source-of-a-memory-leak-712667bf8cd5)

Important to enable malloc stack tracing to see the code source of memory leaks.  Inevitably if you have an instanced commandBuffer that isn't committed in loop will source back to its instance creation as a culprit.  The remedy is easily in loop committing this instanced commandBuffer.

Why re instance commandBuffer?

As it turns out with kernel computations if you are doing complex kernel computation work with multiple pass encodings sequentially.  You can singly instance any device buffers that need be passed to the GPU on kernel instancing (usually at the outside of your viewcontrollers initialization) and then re write to these buffers with memcpy() functions

for instance:

        let hillbufferptr = hilllockbuffer?.contents()
        memcpy(hillbufferptr, &(hilllockLabelMap!),hilllockByteLength)
        let relabelbufferptr = relabelbuffer?.contents()
        memcpy(relabelbufferptr, &(relabelMap!), relabelByteLength)
        let maxhbufferptr = maxhbuffer?.contents()
        memcpy(maxhbufferptr, &(maxHMap!), maxhByteLength)
        plist = [Float32](repeating: -1.0, count: (hillockmatrixtexture?.width)!*(hillockmatrixtexture?.height)!)
        let plistbufferptr = plistbuffer?.contents()
        memcpy(plistbufferptr, &(plist!), plistByteLength)

Then buffers need not be instanced in loop.  Also important instancing textures outside of draw loop otherwise these can translate into memory leaks if not properly dealt with in terms of deallocation.

Anytime data retrieval occurs from a kernel encoding  requires a commandBuffer.commit() and waitUntilCompleted() method...this translates into a new instancing (as far as I can tell) of a commandBuffer.  The memory on the old command Buffer is freed otherwise.

Strategy for complex kernel pass encoding with multiple kernels passing a given data buffer from one kernel to the next.  My advice (as per Apple's direct advice) avoid running a series of commandBuffer.commit() and waitUntilCompleted() method calls for buffer to array call backs only to in turn re write these back to the buffers.  Instead use a single buffer and pass that same pointer buffer from one encoding kernel to the next.  Callback instancing memory with byte copies to an array is slow and will likely cause GPU to hang error messages...or as an engineer describes this is merely serializing data flow from the CPU to the GPU.  It is slow and cumbersome.   I personally found only one instance where CPU processing data was used...my instance was CPU processing array data needed to sort and create set instancing of array data: sorting an array and eliminating duplicate values.  This data would in turn determine the iterative structure of added encoding necessary to the algorithm.

I haven't found a recipe nor have been able to construct an adequate recipe in passing something like float array data into structs and pointing to the struct with such objects since working with instanced struct data (unless it is in pointer form) in the struct on the GPU side has a discretely defined array container size...instead I've just passed array pointers directly to the kernel functions as needed.  Plenty of code recipes for this.

Monday, September 25, 2017

Guild Wars 2 Path of Fire -The Departing Eater of Souls strategy

Early spoiler beta.  The eater of souls will regenerate health after leap attack with tractor beam health siphon.  The strategy to this fight is to run opposite the beam and do a double evade on it at the same time when he launches the health drain.  When far enough away the siphon will do no damage and the Eater of Souls regenerates no health. 

Thursday, September 14, 2017

Dynamic map storage on a texture map in Metal 2(Apple)

   The idea is pretty straightforward here.  Namely, to implement this form of storage, you will probably want a texture that has at least 2 channels, but this can also work for 4 channels with 2 channels reserved for the key value map storage.  

It would be noted that in fact the 'dynamic' storage portion of this storage is actually reserved storage space containing texture.width*texture.height possible indices for storage.  Keying without any layer of lexical enumeration between indices would be an added implementation beyond the scope of what I'd like to cover in this article.  So it is assumed that the indices given by the total range on the set, will serve directly as the key value, and thus the mapped key will have such value.  Thus the key 1 is mapped to index 1 on the texture storage set.  

To map these hash values means then to have some storage value likely a boolean value 1 indicating the hash bucket is reserved,  or 0 that it isn't reserved.

The formulation for converting from a 2d array to 1d array is pretty simple.  

y = indexkey/ texture.width
x = indexkey% texture.width

Thus in metal if your texture point is set with a half4 vector

You can say reserve at such index by accessing (via sample or write) the position:
where 
samp = sampler
uint2 indexval = (indexkey/texture.width, indexkey%texture.width);
half4 color = currenttexture.sample(samp, indexval);
color.zw = half2(1.0, value);
desttexture.write(color,indexval);

Thus mapping to latter two channels on destination texture transposing first 2 channel values from the original texture.  

Lookups then are pretty straight forward if the key is known just plug into x,y formulation above and control check for boolean positive (storage allocation) and then its corresponding value pair.  Noted this is for half format numbers.

Oblivion

 Between the fascination of an upcoming pandemic ridden college football season, Taylor Swift, and Kim Kardashian, wildfires, crazier weathe...