bizcharts example : Doughnut Chart

Chart UI

chart_examples

key codes explaintion:

<Coord type='theta' innerRadius={0.45} />
without 'innerRadius={0.45}', UI will looks like:
chart_examples_full
without below codes, UI will looks like:
<Geom select={[false,{}]} type='intervalStack' position='percent' 
  color={['type', ['rgba(255, 255, 255, 0)']]} 
  style={{stroke: 'rgba(152,191,182,1)', lineWidth: 1}}> 
</Geom> 
chart_examples_null

Codes

ChartComponent.js
import React, { Component } from 'react';
import {Chart, Axis, Tooltip, Geom, Coord, Label} from 'bizcharts';
import DataSet from '@antv/data-set';
const { DataView } = DataSet;

export class ScoreChart extends Component {
  render() {
    const { width, height, score } = this.props;
    const scoreData = [
      { type: 'Score', value: score },
      { type: '', value: 10 - score },
    ];
    const scoreDv = new DataView();
    scoreDv.source(scoreData)
      .transform({
      type: 'percent',
      field: 'value',
      dimension: 'type',
      as: 'percent'
    });
    const scoreColor = (type) => {
      if (type === 'Score')
        return 'rgb(152,191,182)';
      return 'white';
    };
    return (
      <Chart data={scoreDv} width={width} height={height} padding='auto'>
        <Coord type='theta' innerRadius={0.45} />
        <Geom select={[false,{}]} type='intervalStack' position='percent'
          color={['type', ['rgba(255, 255, 255, 0)']]}
          style={{stroke: 'rgba(152,191,182,1)', lineWidth: 1}}>
        </Geom>
        <Geom select={[false,{}]} type='intervalStack' position='percent'
          color={['type', scoreColor]}>
        </Geom>
      </Chart>
    )
  }
};

export class StarChart extends Component {
  render() {
    let { width, height, situation, action, task, result } = this.props;
    if (width < 200)
      width = 200;
    if (height < 200)
      height = 200;
    const starData = [
      { type: 'Situation', value: situation },
      { type: 'Action', value: action },
      { type: 'Task', value: task },
      { type: 'Result', value: result },
    ];
    const starDv = new DataView();
    starDv.source(starData)
      .transform({
      type: 'percent',
      field: 'value',
      dimension: 'type',
      as: 'percent'
    });
    const starColor = (type) => {
      if (type === 'Situation')
        return 'rgb(208,210,211)';
      if (type === 'Action')
        return 'rgb(151,191,182)';
      if (type === 'Task')
        return 'rgb(236,142,91)';
      if (type === 'Result')
        return 'rgb(64,43,74)';
      return 'transparent';
    };
    return (
      <Chart data={starDv} width={width} height={height} padding={['10%', '22%']}>
        <Coord type='theta' innerRadius={0.45} />
        <Geom select={[false,{}]} type='intervalStack' position='percent'
          color={['type', starColor]}>
          <Label content='type' offset={20}/>
        </Geom>
      </Chart>
    )
  }
}
App.js
import React, { Component } from 'react';
import {ScoreChart, StarChart} from './ChartComponent';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <StarChart width={200} height={200}
          situation={20} action={40} task={40} result={20}>
        </StarChart>
        <ScoreChart width={120} height={120}
          score={7}>
        </ScoreChart>
      </div>
    );
  }
}

export default App;

Dependences

yarn add bizcharts yarn add @antv/data-set 

Refers

https://alibaba.github.io/BizCharts/demo-detail.html?code=demo/g2/clock
https://github.com/alibaba/BizCharts/tree/master/doc/tutorial

sed replace shell variable which include slash ('/')

Test content

cat test-sed.txt
aaa/bbb/ccc/ddd/eee
fff/ggg/ss

replace "ccc/ddd" to "CCC/DDD" via sed

NEW_STRING="CCC/DDD"
sed -i "s:ccc/ddd:${NEW_STRING}:" test-sed.txt

Notes:

  1. use ':' as seperate char rather than '/', which is default
  2. use "" include the replace command

Await is a reserved word error

Solution:

In order to use await, the function directly enclosing it needs to be async.
example codes:

async tryGetUserName() {   let session = await Auth.currentSession();   ...... } 

async should be there, otherwise you will get the error.

Fix up: Can't Load URL: The domain of this URL isn't included in the app's domains.

Issue

cannotloadurl_fb_share
Can't Load URL: The domain of this URL isn't included in the app's domains. To be able to load this URL, add all domains and subdomains of your app to the App Domains field in your app settings.

Scenario

  1. create a facebook app to get an appid
  2. use that appid in website to initialized the facebook javascript SDK
  3. use FB.ui to share content to facebook

full source codes

<!-- init facebook js sdk via your appid -->
<script>
  window.fbAsyncInit = function() {
    FB.init({
      appId            : 'yourappid',
      autoLogAppEvents : true,
      xfbml            : true,
      version          : 'v3.1'
    });
  };
  (function(d, s, id){
     var js, fjs = d.getElementsByTagName(s)[0];
     if (d.getElementById(id)) {return;}
     js = d.createElement(s); js.id = id;
     js.src = "https://connect.facebook.net/en_US/sdk.js";
     fjs.parentNode.insertBefore(js, fjs);
   }(document, 'script', 'facebook-jssdk'));
</script>
<script>
function share() {
    // use FB.ui() to share content to facebook
    FB.ui(
      {
        method: 'share',
        href: 'urlyouwanttoshare',
      },
      // callback
      function(response) {
        if (response && !response.error_message) {
          alert('Posting completed.');
        } else {
          alert('Error while posting.');
        }
      }
    );
}
</script>

<button onclick="share()">share</button>

Solution

1.Go to your app in facebook developers page(Settings->Basic)
2.Scroll down and Click on Add platform, choose Web sites
addplatform_website
3.Input your website domain
if you are testing via http://localhost:8080 then input http://localhost:8080
4.Save the changes
Then test again. you will find everything goes well.
sharewell

Notes

App Domains is not working for web site share to facebook.
That might be used for mobile apps.

connect shadowsocks server on ubuntu via ss-local

#Server config
[Set up your own shadowsocks server](https://errong.win/2018/06/05/setup-shadowsocks-on-ubuntu-16-04/) or found/buy one.
You should have a shadowsocks server with below informations:
* server ip
* server port
* password
* method

#install
~~~
sudo apt-get install software-properties-common -y
sudo add-apt-repository ppa:max-c-lv/shadowsocks-libev -y
sudo apt-get update
sudo apt install shadowsocks-libev
~~~

#configure
match to the server's info.
~~~
sudo vim /etc/shadowsocks-libev/config.json
{
    "server":"xx.xx.xx.xx", // server IP
    "server_port":8911,
    "local_port":1008, // local port
    "password":"jesuslove",
    "timeout":60,
    "method":"chacha20-ietf-poly1305"
}
~~~

#run ss-local
```sudo ss-local -c  /etc/shadowsocks-libev/config.json```

#export socks proxy system wide
~~~
export http_proxy=socks5://127.0.0.1:1008
export https_proxy=socks5://127.0.0.1:1008
~~~

#use proxy extension set for chrome/firefox browser
config your proxy extension in your browser to use socks5 proxy
127.0.0.1:1008

c++: Max Heap Template

https://en.wikipedia.org/wiki/Min-max_heap
My simple implementation of max heap.
Change the compare from > to < in below codes, you will get a min heap.

template<typename T>
class MaxHeap {
public:
 MaxHeap() {
  size_ = 0;
  capacity_ = 2;
  heap_ = new T[capacity_];
 }
 MaxHeap(int capacity) {
  if (capacity >= 2) {
   heap_ = new T[capacity];
   capacity_ = capacity;
   size_ = 0;
  }
  else {
   size_ = 0;
   capacity_ = 2;
   heap_ = new T[capacity_];
  }
 }
 ~MaxHeap() {
  if (heap_)
   delete[] heap_;
 }
public:
 int size() { return size_; }
 void insert(const T& t) {
  if ((size_+1) >= capacity_) {
   capacity_ *= 2;
   T* tmp = new T[capacity_];
   for (int i = 0; i <= size_; i++)
    tmp[i] = heap_[i];
   delete[] heap_;
   heap_ = tmp;
  }
  size_++;
  heap_[size_] = t;
  int i = size_;
  int tmp = heap_[i];
  while (i > 1 && tmp > heap_[i / 2]) {
   heap_[i] = heap_[i / 2];
   heap_[i / 2] = tmp;
   tmp = heap_[i / 2];
   i /= 2;
  }
  heap_[i] = tmp;
 }
 T max() {
  return heap_[1];
 }
 int index(const T& t) {
  return index(1, t);
 }
 void removeByIndex(int i) {
  if (i < 1)
   return;
  if (heap_[size_] == heap_[i]) {
   heap_[i] = heap_[size_];
   size_--;
   return;
  }
  if (heap_[size_] < heap_[i]) {
   heap_[i] = heap_[size_];
   size_--;
   maxDown(i);
   return;
  }
  heap_[i] = heap_[size_];
  size_--;
  maxUp(i);
 }
 void remove(const T& t) {
  return removeByIndex(index(t));
 }
private:
 inline int index(int i, const T& t) {
  if (heap_[i] < t)
   return -1;
  if (heap_[i] == t)
   return i;
  int r = index(2 * i, t);
  if (r != -1)
   return r;
  return index(2 * i + 1, t);
 }
 inline void maxDown(int i) {
  if (i * 2 > size_ && (i * 2 + 1) > size_)
   return;
  int l = i * 2;
  int r = l + 1;
  int m = l;
  if (r <= size_ && heap_[r] > heap_[l])
   m = r;
  if (heap_[m] <= heap_[i])
   return;
  T tmp = heap_[i];
  heap_[i] = heap_[m];
  heap_[m] = tmp;
  maxDown(m);
 }
 inline void maxUp(int i) {
  if (i <= 1)
   return;
  int p = i / 2;
  if (heap_[p] >= heap_[i])
   return;
  T tmp = heap_[i];
  heap_[i] = heap_[p];
  heap_[p] = tmp;
  maxUp(p);
 }
private:
 T* heap_;
 int capacity_;
 int size_;
};

static MaxHeap<int>* all[101] = { 0, };
static int mt = 0;

void Init()
{
 for (int i = 1; i < mt; i++)
  if (all[i]) {
   delete all[i];
   all[i] = 0;
  }
 mt = 0;
}

void insertID(int ProductType, int ProductID)
{
 if (!all[ProductType])
  all[ProductType] = new MaxHeap <int>(50001) ;
 all[ProductType]->insert(ProductID);
 if ((ProductType + 1) > mt)
  mt = ProductType + 1;
}

int highestID(int ProductType)
{
 if (!all[ProductType] || all[ProductType]->size() <= 0)
  return -1;
 return all[ProductType]->max();
}

int findhighestID(int type)
{
 int maxType = -1;
 int maxId = -1;
 for (int i = 1; i < mt; i++)
  if (all[i] && all[i]->size() > 0) {
   int max = all[i]->max();
   if (max > maxId) {
    maxId = max;
    maxType = i;
   }
  }
 if (type == 0)
  return maxType;
 return maxId;
}

void demarket(int ProductID)
{
 for (int i = 1; i < mt; i++)
  if (all[i]) {
   int index = all[i]->index(ProductID);
   if (index >= 1) {
    all[i]->removeByIndex(index);
    break;
   }
  }
}

Ember.js : Custom "index" route's path and Custom "/" path's route

"index" Route

The index route, which will handle requests to the root URI (/) of our site.
How to generate a new route called index:
ember g route index
The index route is special: it does NOT require an entry in the router's mapping.

a Nested "index" Route

An index nested route works similarly to the base index route. It is the default route that renders when no route is provided. Use 'rentals' as example, when we navigate to /rentals, Ember will attempt to load the rentals index route as a nested route.
To create an index nested route, run the following command:
ember g route rentals/index
If you open up your Router (app/router.js) you may notice that the rentals line has changed. This extra function() {} is required because it needs a child route, the this.route('index', { path: '/'}); is implied.
Router.map(function() {
  this.route('about');
  this.route('contact');
  this.route('rentals', function() {
    // implied code
    // this.route('index', { path: '/'});
  });
});

replaceWith and transitionTo

Use "replaceWidth" and "transitionTo", We can simply forward "/" to the "rentals" route. You will found the url displayed in url bar will changed from "http://localhost" to "http://localhost/rentals".
Well, everything is fine here except one little fault.
I do not want this redirect from "/" to "/rentals".
I hope it always be "/".
Can we make it ?

Is "index/index" possible ?

I tried below command:
ember g route index/index
installing route
  create app/routes/index/index.js
  create app/templates/index/index.hbs
updating router
  add route index/index
installing route-test
  create tests/unit/routes/index/index-test.js
Command execute without errors, but blank page showed with "http://localhost".
It seems not work. Then I remember the impled code:
this.route('index', { path: '/'});
However, you can add the index route if you want to customize it. For example, you can modify the index route's path by specifying this.route('index', { path: '/custom-path'}).

Custom "index" route's path

We can custom "index" route's path by the impled code.
I guess We can custom the path's route also.
this.route('rentals', {path:'/'});
Ember server will handle requests to the root URI (/) to route "rentals" rather than the default "index" route now.
Can it works ? Let's try

Custom path's route

I use super-rentals as a example.
First I destroy "index" route.
ember d route index
Modify the app router.
git diff app/router.js
diff --git a/app/router.js b/app/router.js
index 254d53d..9f14d85 100644
--- a/app/router.js
+++ b/app/router.js
@@ -9,7 +9,7 @@ const Router = EmberRouter.extend({
 Router.map(function() {
   this.route('about');
   this.route('contact');
-  this.route('rentals', function() {
+  this.route('rentals', {path:'/'}, function() {
     this.route('show', { path: '/:rental_id' });
   });
 });
 
Modify templates, all link to "index" replaced with "rentals".
-  {{#link-to 'index' class="button"}}
+  {{#link-to 'rentals' class="button"}}
 
ember serve
I got what I wished.
The url bar is clean now.
Only "http://localhost", no "rentals" anymore.
super-rental

Refers

Routes and templates
Adding Nested Routes

fixed: embedded-redis: Unable to run on macOS Sonoma

Issue you might see below error while trying to run embedded-redis for your testing on your macOS after you upgrade to Sonoma. java.la...