Tuesday 31 July 2018

react UI ant design

https://ant.design/components/button/
https://codesandbox.io/s/jnw46698m3
https://ant.design/components/grid/
https://ant.design/components/menu/
https://ant.design/components/icon/

卡尔加里夏季必逛农贸集市大盘点



夏季除了带着孩子或者全家人一起进山游玩,最适合挎上小篮子,去农贸市场逛逛,挑选新鲜的时令蔬菜和瓜果!

农贸市场跟普通超市不一样,讲究的就是新鲜和无机!看着满眼的新鲜欲滴的蔬果,那是夏季给予的最好回馈。


下面甜筒妹就给大家盘点这个夏日卡尔加里那些秒杀Costco的农贸集市吧!

Summer


夏天
全年营业

Calgary Farmers’ Market


这个城市最大也是最繁华的一个农贸市场,无论是其各种各样的农产品和肉类产品,还是小吃种类丰富的美食广场,都是成为你这个夏季不得不来的理由。 这里还提供烹饪课程和美食导游服务,还有现场音乐和儿童娱乐活动。

地址:510 77 Ave. S.E.
时间:周四~周天,9 a.m. ~ 5 p.m.
联系方式:403-240-9113,
calgaryfarmersmarket.ca
开放时间:全年营业

Crossroads Market

Crossroads是全年营业的精品农贸市场,一部分是季节性露天市场,一部分是跳蚤市场。 顾客可以全年从这里买到不同季节的水果和蔬菜(以及着名的鳄梨酱)。

地址:1235 26 Ave. S.E.
时间:周五~周天,9 a.m. ~ 5 p.m.
联系方式:403-291-5208,
crossroadsmarket.ca
开放时间:室内市场全年开放;季节性市场在6月至10月期间开放

Hillhurst Sunnyside
Farmers’ Market

Hillhurst Sunnyside社区协会经营的这个每周户外市场,既是社区的社交聚会,也是购买食品的地方,有定期的现场音乐和儿童活动,如充气城堡和脸部彩绘。

这里的 夏季市场每年都会在秋季的感恩节前后结束。 之后,HSCA会从10月到5月初的每周三开设了一个室内农贸市场。
地址:Hillhurst Sunnyside Community Centre, 1320 5 Ave. N.W.
时间:每周三,3 p.m. ~ 7 p.m.
联系方式:587-700-9387,
farmersmarket.hillhurstsunnyside.org
开放时间:全年营业

Market on Macleod


这个农贸市场以售卖来自印度,印度尼西亚,墨西哥和乌克兰等当地风味闻名。
地址:7711 Macleod Tr. S.
时间:周四~周天,9 a.m. ~ 5 p.m.
联系方式:587-354-1120,
marketonmacleod.com
开放时间:全年营业

季节性集市

Bridgeland Riverside
Farmers’ Market

这个集市位于社区大厅外,为附近居民提供了新鲜出炉的面包,自制果酱和农场直送农产品。 还为孩子们提供现场音乐和活动。


社区中心也是卡尔加里市民工具库的所在地 - 允许喜欢DIY但缺乏车库空间的公众有机会从200多种工具中借用,每年只需支付60刀的会员费。

地址:917 Centre Ave. N.E.
时间:每周四,3:30 p.m. ~ 7 p.m.
联系方式:bridgelandfarmersmarket.com
开放时间:6月21至10月1

Calgary Grassroots
Deerfoot Farmers’ Market


这个户外季节性市场前身是Northland Village Mall。 现在,它搬到了户外, 但还和以前一样,有超过40家全职供应商销售本地农产品。 同时也是阿尔伯塔阿省官方亲自盖章认证的农贸市场。
地址:Northeast parking lot at Deerfoot City
时间:每周四,3:30 p.m. ~ 7 p.m.
联系方式:403-282-9299,
northlandmarket.ca
开放时间:6月5至9月25

Marlborough Community
Farmers’ Market


这个集市多卖各种当地食品,还有手工自制面包、糕点和果冻、果酱。
地址:Marlborough Community Association, 636 Marlborough Way N.E.
时间:每周四,3 p.m. ~ 7 p.m.
联系方式:403-969-0676,
facebook.com/marlboroughfarmersmarket
开放时间:6月至9月

Market on Stephen Avenue
Farmers' Market


算得上是卡尔加里唯一一个设在市中心的农贸市场,地点就人流密集的斯蒂芬大道(Stephen Avenue)上。你可以去排队买那里小帐篷下出售的小吃,工艺品,或者一些加工农产品。

营业时间一般都在周二,所以在downtown上班的你不妨在午餐或咖啡休息时间来这里逛一逛。
地址:Stephen Avenue
时间:春夏两季的星期二,10 a.m. ~ 4 p.m.
联系方式:marketonstephenavenue.com
开放时间:5月至8月

Triwood Farmers’ Market

来这里摆摊的供应商很多都是本地很有名的商店。例如Cookie Dough YYC,Lemonberry Pastries&Cakes和Mom's Happy Kitchen。 这个市场更适合一家大小来这里享受假日,在共享天伦之乐之余享用新鲜美味的食物。
地址: Triwood Community Association Hall, 2244 Chicoutimi Dr. N.W.
时间:每周四,3 p.m. ~ 7 p.m.
联系方式:403-282-2677, triwoodcommunity.com
开放时间:6月至8月

年度活动集市

Inglewood Night Market

这个位于Inglewood中心社区的每月街区派对都在改造后的国家酒店大楼周围举行。 虽然更多的是手工艺品市场而非农贸市场,但通常会有一些农产加工供应商来这里摆摊,售卖有机的来自B.C.省的新鲜水果。

同时这个集市会持续到晚上,成为一个热闹的夜市。
地址:10 St. and 10 Ave. S.E.,  9 Ave. 南边与 11 St西边交界.
时间:5 p.m. ~ 11 p.m.
联系方式:inglewoodnightmarket.ca
开放时间:8月10,9月14、15
Summer


夏天
这个夏日,
抽个时间,
带上孩子,
带上家人,
约上好友,
一起逛农贸集市吧,
让生活充满新鲜和享受! 

Saturday 28 July 2018

react chart 2 whisker series

project link: https://chuanshuoge1-react-chart3.herokuapp.com/

left random real time data, right whisker chart data, bottom whisker media

change x, y zoom to see detail or big picture

change group to set # of data points in each whisker

whiskerChart.js


import React, { Component } from 'react';
import '../App.css';
import '../../node_modules/react-vis/dist/style.css';

import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import TextField from '@material-ui/core/TextField';

import { Media } from 'reactstrap';
import whiskerPic from '../stock.png'

import {
    XYPlot,
    XAxis,
    YAxis,
    VerticalGridLines,
    HorizontalGridLines,
    LineSeries,
    WhiskerSeries
} from 'react-vis';


const styles = theme => ({
    textFieldShort: {
        margin: 0,
        width: 100,
    },
});

class WhiskerChart extends Component {
    constructor(props) {
        super(props);

        this.state = {
            realTimeData: [],
            lastY: 10,
            lastX: 0,
            lineSeriesXNum: 20,
            whiskerSeriesXNum: 10,
            whiskerSeriesYNum: 3,
            whiskerSeriesGroup: 5,
            whiskerGroupPosition: 0,
            whiskerCurrent: { x: 0, y: 10, xVariance: 0, yVariance: 2, color: '#006600' },
            lastWhiskerY: 10,
            lastWhiskerX: 0,
            whiskerGain: [],
            whiskerLoss: [],
            barPlot: [],
        };
    }

    componentDidMount() {
        this.myTimer = setInterval(() => this.handle_timer(), 1000);
    }

    componentWillUnmount() {
        clearInterval(this.myTimer);
    }

    async handle_timer() {
        //handle real time data
        const stateRealTimeData = [...this.state.realTimeData];
        const xValue = this.state.lastX;

        //generate next y = current y +- 0.5, y can't be negative
        let yValue = Math.random().toFixed(2) - 0.5 + this.state.lastY;
        yValue < 0 ? yValue = 0 : null;

        const newData = { x: xValue, y: yValue };

        //keep real time data at 300 max, new data in, old out
        stateRealTimeData.length > 300 ?
            stateRealTimeData.splice(0, 1) : null;

        stateRealTimeData.push(newData);

        //save real time data
        await this.setState({
            realTimeData: stateRealTimeData,
            lastY: yValue,
            lastX: xValue + 1,
        })

        //handle whiskerData
        const whiskerGain = [...this.state.whiskerGain];
        const whiskerLoss = [...this.state.whiskerLoss];

        //whisker data is a group of real time data, whiskerSeriesGroup determines the # of data in the group
        if (this.state.whiskerGroupPosition === this.state.whiskerSeriesGroup) {
            await this.setState({ whiskerGroupPosition: 0 });

            //slice last few data from real time data
            const slicedData = stateRealTimeData.slice(stateRealTimeData.length - this.state.whiskerSeriesGroup, stateRealTimeData.length);

            //find min max of the sliced
            const sliceYArray = slicedData.map((item, index) => { return item.y });
            const sliceYMax = Math.max(...sliceYArray);
            const sliceYMin = Math.min(...sliceYArray);

            //the upper part of the whisker
            const whiskerGainNew = {
                x: slicedData[0].x,
                y: (this.state.lastWhiskerY + sliceYMax) / 2,
                xVariance: 0,
                yVariance: sliceYMax - this.state.lastWhiskerY,
            }

            //the lower part of the whisker
            const whiskerLossNew = {
                x: slicedData[0].x,
                y: (this.state.lastWhiskerY + sliceYMin) / 2,
                xVariance: 0,
                yVariance: this.state.lastWhiskerY - sliceYMin,
            }

            whiskerGain.push(whiskerGainNew);
            whiskerLoss.push(whiskerLossNew);

            //keep whisker data at 50 max, new data in, old out
            whiskerGain.length > 50 ?
                whiskerGain.splice(0, 1) : null;

            whiskerLoss.length > 50 ?
                whiskerLoss.splice(0, 1) : null;

            //save whisker data
            await this.setState({ whiskerGain: whiskerGain, whiskerLoss: whiskerLoss });

            //plot change from last
            const barPlot = [...this.state.barPlot];
            //keep bar plot at 50 max
            barPlot.length > 50 ?
                barPlot.splice(0, 1) : null;

            //current and previous bar point
            const barDataNow = { x: slicedData[0].x, y: newData.y };
            const barDataPre = { x: slicedData[0].x, y: this.state.lastWhiskerY }
            const barColor = barDataPre.y >= barDataNow.y ? '#cc0000' : '#006600';

            //plot bar
            barPlot.push(
                <LineSeries data={[barDataPre, barDataNow]}
                    stroke={barColor} strokeWidth={100 / this.state.whiskerSeriesXNum} />
            )

            //save bar data
            await this.setState({ barPlot: barPlot });

            //record whiskerY, whiskerX
            await this.setState({
                lastWhiskerY: newData.y,
                lastWhiskerX: newData.x,
            });

        }

        //handle real time data in the newest whisker
        const whiskerNewest = {
            x: this.state.lastWhiskerX,
            y: (this.state.lastWhiskerY + newData.y) / 2,
            xVariance: 0,
            yVariance: Math.abs(this.state.lastWhiskerY - newData.y),
            color: this.state.lastWhiskerY > newData.y ? '#cc0000' : '#006600',
        }

        //save the newest whisker and increment # of data in whisker group by 1
        await this.setState(prevState => {
            return {
                whiskerCurrent: whiskerNewest,
                whiskerGroupPosition: prevState.whiskerGroupPosition + 1,
            }
        });
    }

    handleLineSeriesXNumChange(value) {
        this.setState({ lineSeriesXNum: parseInt(value) })
    }

    handleWhiskerSeriesXNumChange(value) {
        this.setState({ whiskerSeriesXNum: parseInt(value) })
    }

    handleWhiskerSeriesYNumChange(value) {
        this.setState({ whiskerSeriesYNum: parseInt(value) });
    }

    handleWhiskerSeriesGroupChange(value) {
        this.setState({ whiskerSeriesGroup: parseInt(value) });
    }

    render() {
        const { classes } = this.props;
        const stateRealTimeData = [...this.state.realTimeData];
        const whiskerGain = [...this.state.whiskerGain];
        const whiskerLoss = [...this.state.whiskerLoss];
        const barPlot = [...this.state.barPlot];

        //lineSeriesXNum defines the max # of real time data on chart
        const realTimeDataTrimed = stateRealTimeData.length < this.state.lineSeriesXNum ?
            stateRealTimeData :
            stateRealTimeData.splice(stateRealTimeData.length - this.state.lineSeriesXNum, this.state.lineSeriesXNum)

        //whiskerSeriesXNum defines the max # of whiskers on chart
        const whiskerGainTrimed = whiskerGain.length < this.state.whiskerSeriesXNum ?
            whiskerGain :
            whiskerGain.splice(whiskerGain.length - this.state.whiskerSeriesXNum, this.state.whiskerSeriesXNum)

        const whiskerLossTrimed = whiskerLoss.length < this.state.whiskerSeriesXNum ?
            whiskerLoss :
            whiskerLoss.splice(whiskerLoss.length - this.state.whiskerSeriesXNum, this.state.whiskerSeriesXNum)

        //whiskerX tick value
        const whiskerXTickValue = whiskerGainTrimed.map((item, index) => { return item.x });

        //whiskerX domain
        const whiskerXDomain = [whiskerXTickValue[0], this.state.lastWhiskerX + this.state.whiskerSeriesGroup];

        //whiskerY domain
        const whiskerYDomainMin = this.state.lastWhiskerY - this.state.whiskerSeriesYNum < 0 ? 0 : this.state.lastWhiskerY - this.state.whiskerSeriesYNum;
        const whiskerYDomain = [whiskerYDomainMin, this.state.lastWhiskerY + this.state.whiskerSeriesYNum];

        //whiskerSeriesXNum defines # of barplots
        const barPlotTrimed = barPlot.length < this.state.whiskerSeriesXNum ?
            barPlot.map((item, index) => item) :
            barPlot
                .splice(barPlot.length - this.state.whiskerSeriesXNum, this.state.whiskerSeriesXNum)
                .map((item, index) => item)

        return (
            <div>
                <Grid container spacing={24}>
                    <Grid item xs={12} sm={6}>
                        <h4 className="my-subTitle">Real Time Stock Price</h4>

                        {/*-------real time chart zoom-------*/}
                        <TextField
                            required
                            label='X Zoom'
                            onChange={(e) => this.handleLineSeriesXNumChange(e.target.value)}
                            value={this.state.lineSeriesXNum}
                            className={classes.textFieldShort}
                        />

                        <input type="range" min="1" max="300"
                            value={this.state.lineSeriesXNum}
                            onChange={(e) => this.handleLineSeriesXNumChange(e.target.value)}
                        />

                        {/*-------real time chart plot-------*/}
                        <XYPlot
                            width={300}
                            height={300}>
                            <VerticalGridLines />
                            <HorizontalGridLines />
                            <XAxis title="time" />
                            <YAxis title="$/share" />
                            <LineSeries data={realTimeDataTrimed} />
                        </XYPlot>
                    </Grid>

                    <Grid item xs={12} sm={6}>
                        <h4 className="my-subTitle">Whisker Stock Chart</h4>

                        {/*-------whisker chart X zoom-------*/}
                        <TextField
                            required
                            label='X Zoom'
                            onChange={(e) => this.handleWhiskerSeriesXNumChange(e.target.value)}
                            value={this.state.whiskerSeriesXNum}
                            className={classes.textFieldShort}
                        />

                        <input type="range" min="1" max="50"
                            value={this.state.whiskerSeriesXNum}
                            onChange={(e) => this.handleWhiskerSeriesXNumChange(e.target.value)}
                        /><br />

                        {/*-------whisker chart Y zoom-------*/}
                        <TextField
                            required
                            label='Y Zoom'
                            onChange={(e) => this.handleWhiskerSeriesYNumChange(e.target.value)}
                            value={this.state.whiskerSeriesYNum}
                            className={classes.textFieldShort}
                        />

                        <input type="range" min="1" max="10"
                            value={this.state.whiskerSeriesYNum}
                            onChange={(e) => this.handleWhiskerSeriesYNumChange(e.target.value)}
                        /><br />

                        {/*-------whisker chart Group-------*/}
                        <TextField
                            required
                            label='Group'
                            onChange={(e) => this.handleWhiskerSeriesGroupChange(e.target.value)}
                            value={this.state.whiskerSeriesGroup}
                            className={classes.textFieldShort}
                        />

                        <input type="range" min="2" max="15"
                            value={this.state.whiskerSeriesGroup}
                            onChange={(e) => this.handleWhiskerSeriesGroupChange(e.target.value)}
                        />

                        {/*-------whisker chart plot-------*/}
                        <XYPlot
                            width={300}
                            height={300}
                            xDomain={whiskerXDomain}
                            yDomain={whiskerYDomain}>

                            <VerticalGridLines />
                            <HorizontalGridLines />
                            <XAxis title="time" tickValues={whiskerXTickValue} tickLabelAngle={-90} />
                            <YAxis title="$/share" />

                            {/*--------whisker data up to current-------*/}
                            <WhiskerSeries data={whiskerGainTrimed} color='#006600' />
                            <WhiskerSeries data={whiskerLossTrimed} color='#cc0000' />

                            {/*--------current whisker data-------*/}
                            <WhiskerSeries data={[this.state.whiskerCurrent]}
                                color={this.state.whiskerCurrent.color} />

                            {/*-------bar data-------*/}
                            {barPlotTrimed}
                        </XYPlot>
                    </Grid>

                    <Grid item xs={12} sm={12}>
                        {/*-------whisker chart tutorial-------*/}
                        <Media>
                            <Media left href="#">
                                <img src={whiskerPic} alt="whisker pic" />
                            </Media>
                            <Media body>
                                <Media heading>Whisker Chart Tutorial</Media>
                                <a href="https://jpgraph.net/download/manuals/chunkhtml/ch15s04.html" target="_blank">tutorial link</a>
                            </Media>
                        </Media>
                    </Grid>
                </Grid>
            </div>
        );
    }
}

export default withStyles(styles)(WhiskerChart);


reference:
http://chuanshuoge2.blogspot.com/2018/07/react-chart-2-whisker-series.html