<commit_before>angular.module('starter.controllers', [])

    .controller('DashCtrl', function($scope, $ionicPlatform, $ionicScrollDelegate, $ionicUser, $ionicPopup,
                                     $cordovaGeolocation, $timeout, $interval, $http)
    {
        $scope.skipGuide = false;
        if(typeof(Storage) !== "undefined") {
            if (localStorage.getItem("skipGuide") !== null) {
                $scope.skipGuide = localStorage.getItem("skipGuide");
            }
        }
        $scope.shortForecast = true;

        //String
        $scope.address = "";

        //{time: Number, t1h: Number, sky: String, tmn: Number, tmx: Number, summary: String};
        $scope.currentWeather;

        //{day: String, time: Number, t3h: Number, sky: String, pop: Number, tempIcon: String, tempInfo: String, tmn: Number, tmx: Number}
        $scope.timeTable = [];
        //{week: String, sky:String, pop: Number, humidityIcon: String, reh: Number, tmn: Number, tmx: Number};
        $scope.dayTable = [];

        //[ {name: String, values:[{name: String, value: Number}, ]},
        //  {name: String, values:[{name: String, value: number}, ]} ]
        $scope.timeChart;
        //
        $scope.dayChart;

        //10월 8일(수) 12:23 AM
        $scope.currentTimeString;

        //String
        var fullAddress = "";
        var currentTime = new Date();

        //{date: String, sky: String, tmx: Number, tmn: Number, reh: Number}
        var dailyInfoArray = [];

        //{"lat": Number, "long": Number};
        var location;

        /**
         * @param day
         * @param hours
         * @returns {*}
         */
        function getDayString(day, hours) {
            if (hours !== 0) {
                return '';
            }
            switch (day) {
                case -2: return '그제';
                case -1: return '어제';
                case 0: return '오늘';
                case 1: return '내일';
                case 2: return '모레';
                case 3: return '글피';
                default :
                    console.error("Fail to get day string day="+day+" hours="+hours);
                    return '';
            }
        }

        /**
         *
         * @param {number} positionHours
         * @param {number} day
         * @param {number} hours
         * @returns {String}
         */
        function getTimeString(positionHours, day, hours) {
            if (positionHours === hours && day === 0) {
                return '지금';
            }
            return hours+'시';
        }

        /**
         *
         * @param currentHours
         * @returns {number}
         */
        function getPositionHours(currentHours) {
            return Math.floor(currentHours/3)*3;
        }

        /**
         *
         * @param {Number} sky 맑음(1) 구름조금(2) 구름많음(3) 흐림(4) , invalid : -1
         * @param {Number} pty 없음(0) 비(1) 비/눈(2) 눈(3), invalid : -1
         * @param {Number} lgt 없음(0) 있음(1), invalid : -1
         * @param {Boolean} isNight
         */
        function parseSkyState(sky, pty, lgt, isNight) {
            var skyIconName = "";

            switch (pty) {
                case 1:
                    skyIconName = "Rain";
                    if (lgt) {
                        skyIconName += "WithLightning";
                    }
                    return skyIconName;
                case 2:
                    return skyIconName = "RainWithSnow"; //Todo need RainWithSnow icon";
                case 3:
                    return skyIconName = "Snow";
            }

            if (lgt) {
                return skyIconName = "Lightning";
            }

            if (isNight) {
               skyIconName = "Moon";
            }
            else {
                skyIconName = "Sun";
            }

            switch (sky) {
                case 1:
                    return skyIconName;
                case 2:
                    return skyIconName += "WithCloud";
                case 3:
                    return skyIconName = "Cloud"; //Todo need new icon
                case 4:
                    return skyIconName = "Cloud";
            }

            return skyIconName;
        }

        /**
         *
         * @param temp
         * @param tmx
         * @param tmn
         * @returns {string}
         */
        function decideTempIcon(temp, tmx, tmn) {
            var tempIconName = "Temp-";
            var max = tmx-tmn;
            var c = temp - tmn;
            var p = c/max*10;

            if (p>9) { tempIconName += "10";
            }
            else if (p>8) { tempIconName += "09";
            }
            else if (p>7) { tempIconName += "08";
            }
            else if (p>6) { tempIconName += "07";
            }
            else if (p>5) { tempIconName += "06";
            }
            else if (p>4) { tempIconName += "05";
            }
            else if (p>3) { tempIconName += "04";
            }
            else if (p>2) { tempIconName += "03";
            }
            else if (p>1) { tempIconName += "02";
            }
            else { tempIconName += "01";
            }

            return tempIconName;
        }

        /**
         *
         * @param {date: String, lgt: Number, mx: Number, my: Number, pty: Number, reh: Number, rn1: Number,
         *          sky: Number, t1h: Number, time: String, uuu: Number, vec: Number, vvv: Number,
         *          wsd: Number} currentTownWeather
         * @returns {{}}
         */
        function parseCurrentTownWeather(currentTownWeather) {
            var currentForecast = {};
            var time = parseInt(currentTownWeather.time.substr(0,2));
            var isNight = time < 7 || time > 18;
            currentForecast.time = parseInt(currentTownWeather.time.substr(0,2));
            currentForecast.t1h = currentTownWeather.t1h;
            currentForecast.sky = parseSkyState(currentForecast.sky, currentTownWeather.pty,
                        currentTownWeather.lgt, isNight);

            return currentForecast;
        }

        /**
         * YYYYMMDD
         * @param {String} str
         * @returns {*}
         */
        function convertStringToDate(str) {
            var y = str.substr(0,4),
                m = str.substr(4,2) - 1,
                d = str.substr(6,2);
            var D = new Date(y,m,d);
            return (D.getFullYear() == y && D.getMonth() == m && D.getDate() == d) ? D : undefined;
        }

        /**
         *
         * @param {Date} target
         * @param {Date} current
         * @returns {number}
         */
        function getDiffDays(target, current) {
            if (!target || !current) {
                console.log("target or current is invalid");
                return 0;
            }
            var c = new Date(current.getFullYear(), current.getMonth(), current.getDate());
            return Math.ceil((target-c) / (1000 * 3600 * 24));
        }

        /**
         *
         * @param dailyInfoList
         * @param date
         * @returns {*}
         */
        function getDayInfo(dailyInfoList, date) {
            if (dailyInfoList.length === 0) {
                return undefined;
            }

            for(var i=0; i<dailyInfoList.length; i++) {
                if (dailyInfoList[i].date === date) {
                    return dailyInfoList[i];
                }
            }

            return undefined;
        }

        /**
         *
         * @param shortForecastList
         * @returns {Array}
         */
        function parsePreShortTownWeather(shortForecastList) {
            //It's the same type of dailyInfoArray
            var dailyTemp = [];

            shortForecastList.forEach(function (shortForecast) {
                var dayInfo = getDayInfo(dailyTemp, shortForecast.date);
                if (!dayInfo) {
                    var data = {date: shortForecast.date, sky: "Sun", tmx: null, tmn: null, pop: 0, reh: 0};
                    dailyTemp.push(data);
                    dayInfo = dailyTemp[dailyTemp.length-1];
                    dayInfo.sky = parseSkyState(shortForecast.sky, shortForecast.pty, shortForecast.lgt, false);
                }
                if(shortForecast.tmx != -50 && shortForecast.tmx != 0) {
                    dayInfo.tmx = shortForecast.tmx;
                }
                //sometims, t3h over tmx;
                if (shortForecast.t3h > dayInfo.tmx) {
                    dayInfo.tmx = shortForecast.t3h;
                }

                if(shortForecast.tmn != -50 && shortForecast.tmn != 0) {
                    dayInfo.tmn = shortForecast.tmn;
                }
                if (shortForecast.t3h < dayInfo.tmn) {
                    dayInfo.tmn = shortForecast.t3h;
                }

                if (shortForecast.pty > 0) {
                    dayInfo.sky = parseSkyState(shortForecast.sky, shortForecast.pty, shortForecast.lgt, false);
                }
                dayInfo.pop = shortForecast.pop > dayInfo.pop ? shortForecast.pop : dayInfo.pop;
                dayInfo.reh = shortForecast.reh > dayInfo.reh ? shortForecast.reh : dayInfo.reh;
            });

            console.log(dailyTemp);
            return dailyTemp;
        }

        /**
         * r06 6시간 강수량, s06 6시간 신적설,
         * @param {Object[]} shortForecastList
         * @param {Date} currentForecast
         * @param {Date} current
         * @param {Object[]} dailyInfoList
         * @returns {{timeTable: Array, timeChart: Array}}
         */
        function parseShortTownWeather(shortForecastList, currentForecast, current, dailyInfoList) {
            var data = [];
            var positionHours = getPositionHours(current.getHours());

            shortForecastList.every(function (shortForecast) {
                var tempObject = {};
                var time = parseInt(shortForecast.time.slice(0,-2));
                var diffDays = getDiffDays(convertStringToDate(shortForecast.date), current);
                var day = getDayString(diffDays, time);
                var isNight = time < 7 || time > 18;
                var dayInfo = getDayInfo(dailyInfoList, shortForecast.date);
                if (!dayInfo) {
                    console.log("Fail to find dayInfo date="+shortForecast.date);
                    dayInfo = {date: shortForecast.date, tmx: 100, tmn: -49};
                }

                if (diffDays <= -2 && time < positionHours) {
                    //skip object
                    return true;
                }
                if (positionHours === 0 && diffDays <= -3) {
                   //when current time is 0, skip all -3
                    return true;
                }

                tempObject.day = day;
                tempObject.time = getTimeString(positionHours, diffDays, time);
                //It means invaild data
                if (!shortForecast.pop && !shortForecast.sky && !shortForecast.pty && !shortForecast.reh && !shortForecast.t3h) {
                    tempObject.t3h = undefined;
                    tempObject.pop = undefined;
                    tempObject.sky = "Sun";
                    tempObject.tempIcon = "Temp-01";
                }
                else {
                    tempObject.t3h = shortForecast.t3h;
                    tempObject.sky = parseSkyState(shortForecast.sky, shortForecast.pty, shortForecast.lgt, isNight);
                    tempObject.pop = shortForecast.pop;
                    tempObject.tempIcon = decideTempIcon(shortForecast.t3h, dayInfo.tmx, dayInfo.tmn);
                }

                // 단기 예보의 현재(지금) 데이터를 currentForecast 정보로 업데이트
                if (diffDays === 0 && time === positionHours &&
                            (time <= currentForecast.time && currentForecast.time < time+3)) {
                    tempObject.t3h = currentForecast.t1h;
                    tempObject.sky = currentForecast.sky;
                    tempObject.tempIcon = decideTempIcon(currentForecast.t1h, dayInfo.tmx, dayInfo.tmn);
                }

                // 하루 기준의 최고, 최저 온도 찾기
                if (shortForecast.tmx !== 0) {
                    tempObject.tmx = shortForecast.tmx;
                }
                else if (shortForecast.tmn !== 0) {
                    tempObject.tmn = shortForecast.tmn;
                }

                data.push(tempObject);
                if (data.length >= 32) {
                    return false;
                }
                return true;
            });

            if (data.length < 32) {
                var i;
                for (i=0; data.length < 32; i++) {
                    var tempObject = {};
                    tempObject.day = "";
                    tempObject.time = "";
                    //tempObject.t3h = data[data.length-1].t3h;
                    tempObject.t3h = undefined;
                    tempObject.sky = "Sun";
                    tempObject.pop = 0;
                    tempObject.tempIcon = "Temp-01";
                    data.push(tempObject);
                }
            }

            var timeTable = data.slice(8);
            var timeChart = [
                {
                    name: 'yesterday',
                    values: data.slice(0, data.length - 8).map(function (d) {
                        return { name: 'yesterday', value: d };
                    })
                },
                {
                    name: 'today',
                    values: data.slice(8).map(function (d) {
                        return { name: 'today', value: d };
                    })
                }
            ];

            return {timeTable: timeTable, timeChart: timeChart};
        }

        function dayToString(day) {
            switch (day) {
                case 0: return "일"; break;
                case 1: return "월"; break;
                case 2: return "화"; break;
                case 3: return "수"; break;
                case 4: return "목"; break;
                case 5: return "금"; break;
                case 6: return "토"; break;
            }
            return "";
        }

        function decideHumidityIcon(reh) {
            var tempIconName = "Humidity-";

            if (reh == 100) {
               tempIconName += "90";
            }
            else  {
                tempIconName += parseInt(reh/10)*10;
            }
            return tempIconName;
        }

        function convertMidSkyString(skyInfo) {
            switch(skyInfo) {
                case "맑음": return "Sun"; break;
                case "구름조금": return "SunWithCloud"; break;
                case "구름많음": return "SunWithCloud"; break;
                case "흐림": return "Cloud"; break;
                case "구름적고 비": return "Rain"; break;
                case "구름많고 비": return "Rain"; break;
                case "흐리고 비": return "Rain"; break;
                case "구름적고 눈": return "Snow"; break;
                case "구름많고 눈": return "Snow"; break;
                case "흐리고 눈": return "Snow"; break;
            }

            console.log("Fail to convert skystring="+skyInfo);
            return "";
        }

        function getHighPrioritySky(sky1, sky2) {
            if (sky2 === 'Rain') {
                return sky2;
            }

            return sky1;
        }

        function parseMidTownWeather(midData, dailyInfoList, currentTime) {
            if (!midData) {
                console.log("midData is undefined");
                midData = {
                    "forecast": {
                        "date": "20151002",
                        "time": "0600",
                        "pointNumber": "109",
                        "cnt": 0,
                        "wfsv": "이번 예보기간 전반에는 고기압의 영향으로 대체로 맑겠고, 후반에는 고기압의 가장자리에 들어 구름많겠습니다.     \n기온은 평년(최저기온 : 8~11도, 최고기온 : 20~22도)과 비슷하거나 조금 높겠습니다.\n강수량은 평년(1~3mm)보다 적겠습니다.  \n서해중부해상의 물결은 0.5~2.5m로 일겠습니다."
                    },
                    "land": {
                        "date": "20151002",
                        "time": "0600",
                        "regId": "11B00000",
                        "wf3Am": "구름조금",
                        "wf3Pm": "구름많음",
                        "wf4Am": "구름조금",
                        "wf4Pm": "맑음",
                        "wf5Am": "맑음",
                        "wf5Pm": "구름조금",
                        "wf6Am": "구름조금",
                        "wf6Pm": "구름조금",
                        "wf7Am": "구름많음",
                        "wf7Pm": "구름많음",
                        "wf8": "구름많음",
                        "wf9": "구름많음",
                        "wf10": "구름많음",
                        "pf8Am": "구름많음",
                        "pf8Pm": "구름많음",
                        "pf7Am": "구름조금",
                        "pf7Pm": "구름조금",
                        "pf6Am": "구름조금",
                        "pf6Pm": "구름조금",
                        "pf5Am": "구름조금",
                        "pf5Pm": "구름조금",
                        "pf4Am": "구름조금",
                        "pf4Pm": "구름조금",
                        "pf3Am": "구름많음",
                        "pf3Pm": "구름많음",
                        "pf2Am": "흐리고 비",
                        "pf2Pm": "흐리고 비",
                        "pf1Am": "구름조금",
                        "pf1Pm": "구름조금",
                        "pf0Am": "구름많음",
                        "pf0Pm": "구름많음",
                        "wf1Am": "구름조금",
                        "wf1Pm": "구름조금",
                        "wf2Am": "구름조금",
                        "wf2Pm": "구름조금"
                    },
                    "temp": {
                        "date": "20151002",
                        "time": "0600",
                        "regId": "11B20601",
                        "taMin3": 12,
                        "taMax3": 23,
                        "taMin4": 12,
                        "taMax4": 23,
                        "taMin5": 12,
                        "taMax5": 23,
                        "taMin6": 12,
                        "taMax6": 22,
                        "taMin7": 12,
                        "taMax7": 22,
                        "taMin8": 12,
                        "taMax8": 23,
                        "taMin9": 12,
                        "taMax9": 23,
                        "taMin10": 12,
                        "taMax10": 23,
                        "ptaMin8": 18,
                        "ptaMax8": 27,
                        "ptaMin7": 18,
                        "ptaMax7": 28,
                        "ptaMin6": 16,
                        "ptaMax6": 28,
                        "ptaMin5": 15,
                        "ptaMax5": 28,
                        "ptaMin4": 15,
                        "ptaMax4": 27,
                        "ptaMin3": 16,
                        "ptaMax3": 25,
                        "ptaMin2": 17,
                        "ptaMax2": 22,
                        "ptaMin1": 12,
                        "ptaMax1": 21,
                        "ptaMin0": 15,
                        "ptaMax0": 22,
                        "taMin1": 12,
                        "taMax1": 22,
                        "taMin2": 11,
                        "taMax2": 24
                    }
                }
            }

            //{week: "목", sky:"Cloud", pop: 10, humidityIcon:"Humidity-10", reh: 10, tmn: 10, tmx: 28};
            var tmpDayTable = [];
            dailyInfoList.forEach(function (dayInfo) {
                var data = {};
                if (getDiffDays(convertStringToDate(dayInfo.date), currentTime) == 0) {
                    data.week = "오늘";
                }
                else {
                    data.week = dayToString(convertStringToDate(dayInfo.date).getDay());
                }
                data.sky = dayInfo.sky;
                data.pop = dayInfo.pop;
                data.reh = dayInfo.reh;
                data.humidityIcon = decideHumidityIcon(data.reh);
                data.tmx = dayInfo.tmx;
                data.tmn = dayInfo.tmn;
                tmpDayTable.push(data);
            });

            var day = currentTime.getDay() + 2;
            var skyAm;
            var skyPm;

            day = (day+1)%7;
            skyAm = convertMidSkyString(midData.land.wf3Am);
            skyPm = convertMidSkyString(midData.land.wf3Pm);
            tmpDayTable.push({week: dayToString(day), sky: getHighPrioritySky(skyAm, skyPm), tmx: midData.temp.taMax3,
                        tmn: midData.temp.taMin3, humidityIcon: "Humidity-00"});

            day = (day+1)%7;
            skyAm = convertMidSkyString(midData.land.wf4Am);
            skyPm = convertMidSkyString(midData.land.wf4Pm);
            tmpDayTable.push({week: dayToString(day), sky: getHighPrioritySky(skyAm, skyPm), tmx: midData.temp.taMax4,
                        tmn: midData.temp.taMin4, humidityIcon: "Humidity-00"});

            day = (day+1)%7;
            skyAm = convertMidSkyString(midData.land.wf5Am);
            skyPm = convertMidSkyString(midData.land.wf5Pm);
            tmpDayTable.push({week: dayToString(day), sky: getHighPrioritySky(skyAm, skyPm), tmx: midData.temp.taMax5,
                        tmn: midData.temp.taMin5, humidityIcon: "Humidity-00"});

            day = (day+1)%7;
            skyAm = convertMidSkyString(midData.land.wf6Am);
            skyPm = convertMidSkyString(midData.land.wf6Pm);
            tmpDayTable.push({week: dayToString(day), sky: getHighPrioritySky(skyAm, skyPm), tmx: midData.temp.taMax6,
                        tmn: midData.temp.taMin6, humidityIcon: "Humidity-00"});

            day = (day+1)%7;
            skyAm = convertMidSkyString(midData.land.wf7Am);
            skyPm = convertMidSkyString(midData.land.wf7Pm);
            tmpDayTable.push({week: dayToString(day), sky: getHighPrioritySky(skyAm, skyPm), tmx: midData.temp.taMax7,
                        tmn: midData.temp.taMin7, humidityIcon: "Humidity-00"});

            day = (day+1)%7;
            tmpDayTable.push({week: dayToString(day), sky: convertMidSkyString(midData.land.wf8), tmx: midData.temp.taMax8,
                        tmn: midData.temp.taMin8, humidityIcon: "Humidity-00"});

            day = (day+1)%7;
            tmpDayTable.push({week: dayToString(day), sky: convertMidSkyString(midData.land.wf9), tmx: midData.temp.taMax9,
                        tmn: midData.temp.taMin9, humidityIcon: "Humidity-00"});

            day = (day+1)%7;
            tmpDayTable.push({week: dayToString(day), sky: convertMidSkyString(midData.land.wf10), tmx: midData.temp.taMax10,
                        tmn: midData.temp.taMin10, humidityIcon: "Humidity-00"});

            return tmpDayTable;
        }

        /**
         *
         * @param {String} fullAddress 대한민국 천하도 강남시 하늘구 가내동 33-2, 대한민국 서울특별시 라임구 마라동
         * @returns {String[]}
         */
        function splitAddress(fullAddress) {
            var splitAddress = [];
            if (fullAddress && fullAddress.split) {
                splitAddress = fullAddress.split(" ");
            }
            return splitAddress;
        }

        /**
         * It's supporting only korean lang
         * return only city namd and dong name
         * @param {String} fullAddress
         * @returns {string}
         */
        function getShortenAddress(fullAddress) {
            var parsedAddress = splitAddress(fullAddress);
            if (!parsedAddress || parsedAddress.length < 2) {
                console.log("Fail to split full address="+fullAddress);
                return "";
            }
            if (parsedAddress.length === 5) {
                //대한민국, 경기도, 성남시, 분당구, 수내동
                parsedAddress.splice(0, 2);
            }
            else if (parsedAddress.length === 4) {
                //대한민국, 서울특별시, 송파구, 잠실동
                parsedAddress.splice(0, 1);
            }
            else if (parsedAddress.length === 3) {
                //대한민국,세종특별자치시, 금난면,
                parsedAddress.splice(0, 1);
            }
            else {
                console.log('Fail to get shorten from ='+fullAddress);
            }
            parsedAddress.splice(1, 1);
            parsedAddress.splice(2, 1);

            console.log(parsedAddress.toString());

            return parsedAddress.toString();
        }

        /**
         *
         * @param {String[]} addressArray
         * @param {cbWeatherInfo} callback
         */
        function getWeatherInfo(addressArray, callback) {
            //var url = 'town';
            var url = 'https://d2ibo8bwl7ifj5.cloudfront.net/town';
            //var url = 'http://todayweather1-wizardfactory.rhcloud.com/town';

            if (!Array.isArray(addressArray) || addressArray.length === 0) {
                return callback(new Error("addressArray is NOT array"));
            }

            if (addressArray.length === 5) {
                url += '/'+addressArray[1]+'/'+addressArray[2]+addressArray[3]+'/'+addressArray[4];
            }
            else if (addressArray.length === 4) {
                url += '/'+addressArray[1]+'/'+addressArray[2]+'/'+addressArray[3];
            }
            else if (addressArray.length === 3) {
                url += '/'+addressArray[1]+'/'+addressArray[1]+'/'+addressArray[2];
            }
            else {
                var err = new Error("Fail to parse address array="+addressArray.toString());
                console.log(err);
                return callback(err);
            }

            console.log(url);

            $http({method: 'GET', url: url})
                .success(function(data) {
                    console.log(data);
                    callback(undefined, data);
                })
                .error(function(error) {
                    if (!error) {
                        error = new Error("Fail to get weatherInfo");
                    }
                    console.log(error);
                    callback(error);
                });
        }
        /**
         * @callback cbWeatherInfo
         * @param {Error} error
         * @param {Object} data
         */

        /**
         *
         * @param {cbCurrentPosition} callback
         */
        function getCurrentPosition(callback) {
            $cordovaGeolocation.getCurrentPosition({
                enableHighAccuracy: false,
                timeout : 5000
            }).then(function(position) {
                    //경기도,광주시,오포읍,37.36340556,127.2307667
                    //callback(undefined, 37.363, 127.230);
                    //세종특별자치시,세종특별자치시,연기면,36.517338,127.259247
                    //callback(undefined, 36.51, 127.259);
                    callback(undefined, position.coords.latitude, position.coords.longitude);
                }, function (error) {
                    console.log(error);
                    callback(error);
                });
        }
        /**
         * @callback cbCurrentPosition
         * @param {Error} error
         * @param {Number} latitude
         * @param {Number} longitude
         */

        /**
         * It's supporting only korean lang
         * @param {Object[]} results
         * @returns {string}
         */
        function findDongAddressFromGoogleGeoCodeResults(results) {<commit_msg>#163 주간날씨에서 하늘상태, 강수확률 및 습도 표시<commit_after>angular.module('starter.controllers', [])

    .controller('DashCtrl', function($scope, $ionicPlatform, $ionicScrollDelegate, $ionicUser, $ionicPopup,
                                     $cordovaGeolocation, $timeout, $interval, $http)
    {
        $scope.skipGuide = false;
        if(typeof(Storage) !== "undefined") {
            if (localStorage.getItem("skipGuide") !== null) {
                $scope.skipGuide = localStorage.getItem("skipGuide");
            }
        }
        $scope.shortForecast = true;

        //String
        $scope.address = "";

        //{time: Number, t1h: Number, sky: String, tmn: Number, tmx: Number, summary: String};
        $scope.currentWeather;

        //{day: String, time: Number, t3h: Number, sky: String, pop: Number, tempIcon: String, tempInfo: String, tmn: Number, tmx: Number}
        $scope.timeTable = [];
        //{week: String, sky:String, pop: Number, humidityIcon: String, reh: Number, tmn: Number, tmx: Number};
        $scope.dayTable = [];

        //[ {name: String, values:[{name: String, value: Number}, ]},
        //  {name: String, values:[{name: String, value: number}, ]} ]
        $scope.timeChart;
        //
        $scope.dayChart;

        //10월 8일(수) 12:23 AM
        $scope.currentTimeString;

        //String
        var fullAddress = "";
        var currentTime = new Date();

        //{date: String, sky: String, tmx: Number, tmn: Number, reh: Number}
        var dailyInfoArray = [];

        //{"lat": Number, "long": Number};
        var location;

        /**
         * @param day
         * @param hours
         * @returns {*}
         */
        function getDayString(day, hours) {
            if (hours !== 0) {
                return '';
            }
            switch (day) {
                case -2: return '그제';
                case -1: return '어제';
                case 0: return '오늘';
                case 1: return '내일';
                case 2: return '모레';
                case 3: return '글피';
                default :
                    console.error("Fail to get day string day="+day+" hours="+hours);
                    return '';
            }
        }

        /**
         *
         * @param {number} positionHours
         * @param {number} day
         * @param {number} hours
         * @returns {String}
         */
        function getTimeString(positionHours, day, hours) {
            if (positionHours === hours && day === 0) {
                return '지금';
            }
            return hours+'시';
        }

        /**
         *
         * @param currentHours
         * @returns {number}
         */
        function getPositionHours(currentHours) {
            return Math.floor(currentHours/3)*3;
        }

        /**
         *
         * @param {Number} sky 맑음(1) 구름조금(2) 구름많음(3) 흐림(4) , invalid : -1
         * @param {Number} pty 없음(0) 비(1) 비/눈(2) 눈(3), invalid : -1
         * @param {Number} lgt 없음(0) 있음(1), invalid : -1
         * @param {Boolean} isNight
         */
        function parseSkyState(sky, pty, lgt, isNight) {
            var skyIconName = "";

            switch (pty) {
                case 1:
                    skyIconName = "Rain";
                    if (lgt) {
                        skyIconName += "WithLightning";
                    }
                    return skyIconName;
                case 2:
                    return skyIconName = "RainWithSnow"; //Todo need RainWithSnow icon";
                case 3:
                    return skyIconName = "Snow";
            }

            if (lgt) {
                return skyIconName = "Lightning";
            }

            if (isNight) {
               skyIconName = "Moon";
            }
            else {
                skyIconName = "Sun";
            }

            switch (sky) {
                case 1:
                    return skyIconName;
                case 2:
                    return skyIconName += "WithCloud";
                case 3:
                    return skyIconName = "Cloud"; //Todo need new icon
                case 4:
                    return skyIconName = "Cloud";
            }

            return skyIconName;
        }

        /**
         *
         * @param temp
         * @param tmx
         * @param tmn
         * @returns {string}
         */
        function decideTempIcon(temp, tmx, tmn) {
            var tempIconName = "Temp-";
            var max = tmx-tmn;
            var c = temp - tmn;
            var p = c/max*10;

            if (p>9) { tempIconName += "10";
            }
            else if (p>8) { tempIconName += "09";
            }
            else if (p>7) { tempIconName += "08";
            }
            else if (p>6) { tempIconName += "07";
            }
            else if (p>5) { tempIconName += "06";
            }
            else if (p>4) { tempIconName += "05";
            }
            else if (p>3) { tempIconName += "04";
            }
            else if (p>2) { tempIconName += "03";
            }
            else if (p>1) { tempIconName += "02";
            }
            else { tempIconName += "01";
            }

            return tempIconName;
        }

        /**
         *
         * @param {date: String, lgt: Number, mx: Number, my: Number, pty: Number, reh: Number, rn1: Number,
         *          sky: Number, t1h: Number, time: String, uuu: Number, vec: Number, vvv: Number,
         *          wsd: Number} currentTownWeather
         * @returns {{}}
         */
        function parseCurrentTownWeather(currentTownWeather) {
            var currentForecast = {};
            var time = parseInt(currentTownWeather.time.substr(0,2));
            var isNight = time < 7 || time > 18;
            currentForecast.time = parseInt(currentTownWeather.time.substr(0,2));
            currentForecast.t1h = currentTownWeather.t1h;
            currentForecast.sky = parseSkyState(currentForecast.sky, currentTownWeather.pty,
                        currentTownWeather.lgt, isNight);

            return currentForecast;
        }

        /**
         * YYYYMMDD
         * @param {String} str
         * @returns {*}
         */
        function convertStringToDate(str) {
            var y = str.substr(0,4),
                m = str.substr(4,2) - 1,
                d = str.substr(6,2);
            var D = new Date(y,m,d);
            return (D.getFullYear() == y && D.getMonth() == m && D.getDate() == d) ? D : undefined;
        }

        /**
         *
         * @param {Date} target
         * @param {Date} current
         * @returns {number}
         */
        function getDiffDays(target, current) {
            if (!target || !current) {
                console.log("target or current is invalid");
                return 0;
            }
            var c = new Date(current.getFullYear(), current.getMonth(), current.getDate());
            return Math.ceil((target-c) / (1000 * 3600 * 24));
        }

        /**
         *
         * @param dailyInfoList
         * @param date
         * @returns {*}
         */
        function getDayInfo(dailyInfoList, date) {
            if (dailyInfoList.length === 0) {
                return undefined;
            }

            for(var i=0; i<dailyInfoList.length; i++) {
                if (dailyInfoList[i].date === date) {
                    return dailyInfoList[i];
                }
            }

            return undefined;
        }

        /**
         *
         * @param shortForecastList
         * @returns {Array}
         */
        function parsePreShortTownWeather(shortForecastList) {
            //It's the same type of dailyInfoArray
            var dailyTemp = [];

            shortForecastList.forEach(function (shortForecast) {
                var dayInfo = getDayInfo(dailyTemp, shortForecast.date);
                if (!dayInfo) {
                    var data = {date: shortForecast.date, sky: "Sun", tmx: null, tmn: null, pop: 0, reh: 0};
                    dailyTemp.push(data);
                    dayInfo = dailyTemp[dailyTemp.length-1];
                    dayInfo.sky = parseSkyState(shortForecast.sky, shortForecast.pty, shortForecast.lgt, false);
                }
                if(shortForecast.tmx != -50 && shortForecast.tmx != 0) {
                    dayInfo.tmx = shortForecast.tmx;
                }
                //sometims, t3h over tmx;
                if (shortForecast.t3h > dayInfo.tmx) {
                    dayInfo.tmx = shortForecast.t3h;
                }

                if(shortForecast.tmn != -50 && shortForecast.tmn != 0) {
                    dayInfo.tmn = shortForecast.tmn;
                }
                if (shortForecast.t3h < dayInfo.tmn) {
                    dayInfo.tmn = shortForecast.t3h;
                }

                if (shortForecast.pty > 0) {
                    dayInfo.sky = parseSkyState(shortForecast.sky, shortForecast.pty, shortForecast.lgt, false);
                }
                dayInfo.pop = shortForecast.pop > dayInfo.pop ? shortForecast.pop : dayInfo.pop;
                dayInfo.reh = shortForecast.reh > dayInfo.reh ? shortForecast.reh : dayInfo.reh;
            });

            console.log(dailyTemp);
            return dailyTemp;
        }

        /**
         * r06 6시간 강수량, s06 6시간 신적설,
         * @param {Object[]} shortForecastList
         * @param {Date} currentForecast
         * @param {Date} current
         * @param {Object[]} dailyInfoList
         * @returns {{timeTable: Array, timeChart: Array}}
         */
        function parseShortTownWeather(shortForecastList, currentForecast, current, dailyInfoList) {
            var data = [];
            var positionHours = getPositionHours(current.getHours());

            shortForecastList.every(function (shortForecast) {
                var tempObject = {};
                var time = parseInt(shortForecast.time.slice(0,-2));
                var diffDays = getDiffDays(convertStringToDate(shortForecast.date), current);
                var day = getDayString(diffDays, time);
                var isNight = time < 7 || time > 18;
                var dayInfo = getDayInfo(dailyInfoList, shortForecast.date);
                if (!dayInfo) {
                    console.log("Fail to find dayInfo date="+shortForecast.date);
                    dayInfo = {date: shortForecast.date, tmx: 100, tmn: -49};
                }

                if (diffDays <= -2 && time < positionHours) {
                    //skip object
                    return true;
                }
                if (positionHours === 0 && diffDays <= -3) {
                   //when current time is 0, skip all -3
                    return true;
                }

                tempObject.day = day;
                tempObject.time = getTimeString(positionHours, diffDays, time);
                //It means invaild data
                if (!shortForecast.pop && !shortForecast.sky && !shortForecast.pty && !shortForecast.reh && !shortForecast.t3h) {
                    tempObject.t3h = undefined;
                    tempObject.pop = undefined;
                    tempObject.sky = "Sun";
                    tempObject.tempIcon = "Temp-01";
                }
                else {
                    tempObject.t3h = shortForecast.t3h;
                    tempObject.sky = parseSkyState(shortForecast.sky, shortForecast.pty, shortForecast.lgt, isNight);
                    tempObject.pop = shortForecast.pop;
                    tempObject.tempIcon = decideTempIcon(shortForecast.t3h, dayInfo.tmx, dayInfo.tmn);
                }

                // 단기 예보의 현재(지금) 데이터를 currentForecast 정보로 업데이트
                if (diffDays === 0 && time === positionHours &&
                            (time <= currentForecast.time && currentForecast.time < time+3)) {
                    tempObject.t3h = currentForecast.t1h;
                    tempObject.sky = currentForecast.sky;
                    tempObject.tempIcon = decideTempIcon(currentForecast.t1h, dayInfo.tmx, dayInfo.tmn);
                }

                // 하루 기준의 최고, 최저 온도 찾기
                if (shortForecast.tmx !== 0) {
                    tempObject.tmx = shortForecast.tmx;
                }
                else if (shortForecast.tmn !== 0) {
                    tempObject.tmn = shortForecast.tmn;
                }

                data.push(tempObject);
                if (data.length >= 32) {
                    return false;
                }
                return true;
            });

            if (data.length < 32) {
                var i;
                for (i=0; data.length < 32; i++) {
                    var tempObject = {};
                    tempObject.day = "";
                    tempObject.time = "";
                    //tempObject.t3h = data[data.length-1].t3h;
                    tempObject.t3h = undefined;
                    tempObject.sky = "Sun";
                    tempObject.pop = 0;
                    tempObject.tempIcon = "Temp-01";
                    data.push(tempObject);
                }
            }

            var timeTable = data.slice(8);
            var timeChart = [
                {
                    name: 'yesterday',
                    values: data.slice(0, data.length - 8).map(function (d) {
                        return { name: 'yesterday', value: d };
                    })
                },
                {
                    name: 'today',
                    values: data.slice(8).map(function (d) {
                        return { name: 'today', value: d };
                    })
                }
            ];

            return {timeTable: timeTable, timeChart: timeChart};
        }

        function dayToString(day) {
            switch (day) {
                case 0: return "일"; break;
                case 1: return "월"; break;
                case 2: return "화"; break;
                case 3: return "수"; break;
                case 4: return "목"; break;
                case 5: return "금"; break;
                case 6: return "토"; break;
            }
            return "";
        }

        function decideHumidityIcon(reh) {
            var tempIconName = "Humidity-";

            if (reh == 100) {
               tempIconName += "90";
            }
            else  {
                tempIconName += parseInt(reh/10)*10;
            }
            return tempIconName;
        }

        function convertMidSkyString(skyInfo) {
            switch(skyInfo) {
                case "맑음": return "Sun"; break;
                case "구름조금": return "SunWithCloud"; break;
                case "구름많음": return "SunWithCloud"; break;
                case "흐림": return "Cloud"; break;
                case "구름적고 비": return "Rain"; break;
                case "구름많고 비": return "Rain"; break;
                case "흐리고 비": return "Rain"; break;
                case "구름적고 눈": return "Snow"; break;
                case "구름많고 눈": return "Snow"; break;
                case "흐리고 눈": return "Snow"; break;
            }

            console.log("Fail to convert skystring="+skyInfo);
            return "";
        }

        function getHighPrioritySky(sky1, sky2) {
            if (sky2 === 'Rain') {
                return sky2;
            }

            return sky1;
        }

        function parseMidTownWeather(midData, dailyInfoList, currentTime) {
            if (!midData) {
                console.log("midData is undefined");
                midData = {
                    "forecast": {
                        "date": "20151005",
                        "time": "1800",
                        "pointNumber": "109",
                        "cnt": 0,
                        "wfsv": "기압골의 영향으로 10일에 비가 오겠으며, 그 밖의 날에는 고기압의 가장자리에 들어 가끔 구름많겠습니다.     \n기온은 평년(최저기온 : 7~11도, 최고기온 : 20~22도)과 비슷하겠습니다. \n강수량은 평년(0~3mm)과 비슷하겠습니다.  \n서해중부해상의 물결은 10일과 11일에는 1.0~2.5m로 일겠고, 그 밖의 날은 0.5~2.0m로 일겠습니다."
                    },
                    "dailyData": [{
                        "date": "20150928",
                        "wfAm": "구름조금",
                        "wfPm": "구름조금",
                        "taMin": 15,
                        "taMax": 28
                    }, {
                        "date": "20150929",
                        "wfAm": "구름조금",
                        "wfPm": "구름조금",
                        "taMin": 15,
                        "taMax": 27
                    }, {
                        "date": "20150930",
                        "wfAm": "구름많음",
                        "wfPm": "구름많음",
                        "taMin": 16,
                        "taMax": 25
                    }, {
                        "date": "20151001",
                        "wfAm": "흐리고 비",
                        "wfPm": "흐리고 비",
                        "taMin": 17,
                        "taMax": 22
                    }, {
                        "date": "20151002",
                        "wfAm": "구름조금",
                        "wfPm": "구름조금",
                        "taMin": 12,
                        "taMax": 21
                    }, {
                        "date": "20151003",
                        "wfAm": "구름많음",
                        "wfPm": "구름조금",
                        "taMin": 15,
                        "taMax": 22
                    }, {
                        "date": "20151004",
                        "wfAm": "구름조금",
                        "wfPm": "구름조금",
                        "taMin": 12,
                        "taMax": 22
                    }, {
                        "date": "20151005",
                        "wfAm": "구름조금",
                        "wfPm": "구름많음",
                        "taMin": 11,
                        "taMax": 24
                    }, {
                        "date": "20151006",
                        "wfAm": "맑음",
                        "wfPm": "맑음",
                        "taMin": 11,
                        "taMax": 25
                    }, {
                        "date": "20151007",
                        "wfAm": "맑음",
                        "wfPm": "구름조금",
                        "taMin": 12,
                        "taMax": 25
                    }, {
                        "date": "20151008",
                        "wfAm": "구름많음",
                        "wfPm": "구름많음",
                        "taMin": 13,
                        "taMax": 23
                    }, {
                        "date": "20151009",
                        "wfAm": "구름많음",
                        "wfPm": "구름많음",
                        "taMin": 13,
                        "taMax": 23
                    }, {
                        "date": "20151010",
                        "wfAm": "구름많음",
                        "wfPm": "구름많음",
                        "taMin": 12,
                        "taMax": 21
                    }, {
                        "date": "20151011",
                        "wfAm": "구름많고 비",
                        "wfPm": "흐리고 비",
                        "taMin": 11,
                        "taMax": 18
                    }, {
                        "date": "20151012",
                        "wfAm": "구름많음",
                        "wfPm": "구름많음",
                        "taMin": 10,
                        "taMax": 19
                    }, {
                        "date": "20151013",
                        "wfAm": "구름많음",
                        "wfPm": "구름많음",
                        "taMin": 10,
                        "taMax": 21
                    }, {
                        "date": "20151014",
                        "wfAm": "구름조금",
                        "wfPm": "구름조금",
                        "taMin": 10,
                        "taMax": 21
                    }, {
                        "date": "20151015",
                        "wfAm": "구름조금",
                        "wfPm": "구름조금",
                        "taMin": 10,
                        "taMax": 22
                    }, {
                        "date": "20151016",
                        "wfAm": "구름조금",
                        "wfPm": "구름조금",
                        "taMin": 10,
                        "taMax": 22
                    }]
                }
            }

            var tmpDayTable = [];
            midData.dailyData.forEach(function(dayInfo) {
                var data = {};

                data.date = dayInfo.date;
                if (getDiffDays(convertStringToDate(data.date), currentTime) == 0) {
                    data.week = "오늘";
                }
                else {
                    data.week = dayToString(convertStringToDate(data.date).getDay());
                }

                var skyAm = convertMidSkyString(dayInfo.wfAm);
                var skyPm = convertMidSkyString(dayInfo.wfPm);
                data.sky = getHighPrioritySky(skyAm, skyPm);
                data.tmx = dayInfo.taMax;
                data.tmn = dayInfo.taMin;
                data.humidityIcon = "Humidity-00";
                tmpDayTable.push(data);
            });

            console.log(tmpDayTable);

            var index = 0;
            for (var i=0; i<tmpDayTable.length; i++) {
                var tmpDate = dailyInfoList[0].date;
                console.log(tmpDate);
                if (tmpDayTable[i].date === tmpDate) {
                    index = i;
                    break;
                }
            }

            //{week: "목", sky:"Cloud", pop: 10, humidityIcon:"Humidity-10", reh: 10, tmn: 10, tmx: 28};
            dailyInfoList.forEach(function (dayInfo) {
                var data;
                if (tmpDayTable[index].date === dayInfo.date) {
                    data = tmpDayTable[index];
                    data.sky = dayInfo.sky;
                    data.pop = dayInfo.pop;
                    data.reh = dayInfo.reh;
                    data.humidityIcon = decideHumidityIcon(data.reh);
                    index++;
                }
                else {
                    console.log("Date was mismatched index:"+index+" date:"+tmpDayTable[index].date+
                                " dayInfo.date="+dayInfo.date);
                }
            });

            return tmpDayTable;
        }

        /**
         *
         * @param {String} fullAddress 대한민국 천하도 강남시 하늘구 가내동 33-2, 대한민국 서울특별시 라임구 마라동
         * @returns {String[]}
         */
        function splitAddress(fullAddress) {
            var splitAddress = [];
            if (fullAddress && fullAddress.split) {
                splitAddress = fullAddress.split(" ");
            }
            return splitAddress;
        }

        /**
         * It's supporting only korean lang
         * return only city namd and dong name
         * @param {String} fullAddress
         * @returns {string}
         */
        function getShortenAddress(fullAddress) {
            var parsedAddress = splitAddress(fullAddress);
            if (!parsedAddress || parsedAddress.length < 2) {
                console.log("Fail to split full address="+fullAddress);
                return "";
            }
            if (parsedAddress.length === 5) {
                //대한민국, 경기도, 성남시, 분당구, 수내동
                parsedAddress.splice(0, 2);
            }
            else if (parsedAddress.length === 4) {
                //대한민국, 서울특별시, 송파구, 잠실동
                parsedAddress.splice(0, 1);
            }
            else if (parsedAddress.length === 3) {
                //대한민국,세종특별자치시, 금난면,
                parsedAddress.splice(0, 1);
            }
            else {
                console.log('Fail to get shorten from ='+fullAddress);
            }
            parsedAddress.splice(1, 1);
            parsedAddress.splice(2, 1);

            console.log(parsedAddress.toString());

            return parsedAddress.toString();
        }

        /**
         *
         * @param {String[]} addressArray
         * @param {cbWeatherInfo} callback
         */
        function getWeatherInfo(addressArray, callback) {
            //var url = 'town';
            var url = 'https://d2ibo8bwl7ifj5.cloudfront.net/town';
            //var url = 'http://todayweather1-wizardfactory.rhcloud.com/town';

            if (!Array.isArray(addressArray) || addressArray.length === 0) {
                return callback(new Error("addressArray is NOT array"));
            }

            if (addressArray.length === 5) {
                url += '/'+addressArray[1]+'/'+addressArray[2]+addressArray[3]+'/'+addressArray[4];
            }
            else if (addressArray.length === 4) {
                url += '/'+addressArray[1]+'/'+addressArray[2]+'/'+addressArray[3];
            }
            else if (addressArray.length === 3) {
                url += '/'+addressArray[1]+'/'+addressArray[1]+'/'+addressArray[2];
            }
            else {
                var err = new Error("Fail to parse address array="+addressArray.toString());
                console.log(err);
                return callback(err);
            }

            console.log(url);

            $http({method: 'GET', url: url})
                .success(function(data) {
                    console.log(data);
                    callback(undefined, data);
                })
                .error(function(error) {
                    if (!error) {
                        error = new Error("Fail to get weatherInfo");
                    }
                    console.log(error);
                    callback(error);
                });
        }
        /**
         * @callback cbWeatherInfo
         * @param {Error} error
         * @param {Object} data
         */

        /**
         *
         * @param {cbCurrentPosition} callback
         */
        function getCurrentPosition(callback) {
            $cordovaGeolocation.getCurrentPosition({
                timeout : 3000
            }).then(function(position) {
                    //경기도,광주시,오포읍,37.36340556,127.2307667
                    //callback(undefined, 37.363, 127.230);
                    //세종특별자치시,세종특별자치시,연기면,36.517338,127.259247
                    //callback(undefined, 36.51, 127.259);
                    callback(undefined, position.coords.latitude, position.coords.longitude);
                }, function (error) {
                    console.log(error);
                    callback(error);
                });
        }
        /**
         * @callback cbCurrentPosition
         * @param {Error} error
         * @param {Number} latitude
         * @param {Number} longitude
         */

        /**
         * It's supporting only korean lang
         * @param {Object[]} results
         * @returns {string}
         */
        function findDongAddressFromGoogleGeoCodeResults(results) {
{'fraction_non_alphanumeric': 0.11869061757719715, 'fraction_numerical': 0.021470457244655582, 'mean_word_length': 1.1278973346495558, 'pattern_counts': {'":': 213, '<': 28, '<?xml version=': 0, '>': 35, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7192907', 'n_tokens_mistral': 16784, 'n_tokens_neox': 15888, 'n_words': 3121}