Fate???

>Do you believe in fate?
>>No, I believe in free will.
>Why?
>>That's how I found you. I choose to love you, but it's unimaginable to forget you.
>I'm not going anywhere. Just gave me time.
>>Time? *sigh
>Time to prepare myself. We're getting married soon, right?
>>LOL
>Why are you laughing?
>>Nah. Happiness, maybe?
>Girl, >>Boy


GeoDjango + GeoServer + Openlayers Combo!

I am developing this web mapping application using Django(GeoDjango), Openlayers and PostgreSQL(PostGIS plugin). It is quite good but when having a huge set of data(shapefile/rows in the table/polygons with multiple vertices) it is "laggy". Panning and browsing on the map and rendering of layers is too slow.

I have read some articles about it that although Openlayers has no limitation in rendering a vector(feature) layer, the browser does. So, I decided to use GeoServer.

Here's my framework for now:

web mapping framework

Before, I get my GeoJSON data from Django and rendered it directly using Openlayers but since it is, as I said "laggy" the visualization of the map now is from GeoServer (WMS). HUGE difference, in terms of its rendering performance. It is quite good but I need to learn more about tuning it and use native JAI for rendering images.

And also, performing PostGIS queries(ST_Intersects, etc...) is slow, I have tried using raw sql for it but still the response time is unacceptable.

Few more notes, I am still using Django 1.6.3, Openlayers 2.14, PostgreSQL 9.3 with PostGIS and GeoServer 2.7.2. Of course, have some plan in upgrading it but I don't know when. HAHA

The project is under development but you can visit it with this link.
Thanks to my two friends for helping me in deploying it. HAHA :)

Echo of Soul: Huntress Quickdraw Build

So, I've been playing this game for a month now. Currently I'm level 55 and my class is obviously a Huntress. Anyway, here's my build:
Skill Build Huntress: Echo of Soul
SKILL BUILD

I don't have plan on getting any skills from the last line. :D
No hate on Sniper Stance though. I just want a quick and agile character.

Skill Build Huntress Series: Echo of Soul
Skill Series

The way I kill enemies(monsters) is the same with characters(PvP).
  • Cast the Nervous Target skill to them (F7)
  • Slow them down and decrease their defence; Stunning Shot (1)
  • Cast Nock Twice(2) to restore CP then Withering Arrow(skill trigger, probably Q or E) to decrease more defence on the enemy
  • Poison;Arsenic Arrow(3)
  • As they approach you, cast Know Back; Suppressing Shot(4) 
  • Lighten Quiver(5) then skill trigger; Bullseye Splitter
  • If still alive, cast Violent Retreat (F1) to stay away from the them
  • Then cast Kill Shot(F2)
Probably, that's how I play. :)

And a simple tip in Battlefield:
  • use Soul Skill(hotkey T) when dealing with lots of enemy then cast Blindfire(F4) then Bombardment(6)
  • use Tab when targeting enemy, it will automatically point on the enemy(this is how I got 20+ kills every battle) 
  • do not use Elusion(F12) unless you're tracking down an enemy
  • cast F9(forgot the skill name) when your HP is low

Some of my battles:
PvP: Echo of Soul
PvP

PvP: Echo of Soul
PvP

PvP: Echo of Soul
PvP

PvP: Echo of Soul
PvP


I stopped story quest at level 27, started repeatable quest to earn more badges for some awesome stuffs.

Keep gems to enhance your items. Keep your energy up(+10% HP and ATK is great)

Anyway, my IGN is Mimimeow and from Serepha Server. She's so cute. :3
Echo of Soul: Huntress
Mimimeow at 53

Overlaying Legend on Map

This is actually just a simple CSS manipulation, you need to create your legend using an image editor. This won't generate automatically based on your styling.



<!--HTML-->
<div id="map">
  <div id="infoi">
    <img src="https://b3218a0dcf0f0481f4a486b8229300982d8fe048-www.googledrive.com/host/0B0JBx-GczUoYUExkeENEQWFDb00"/>
  </div>
</div>
/*CSS*/
#map {
  width: 500px;
  height: 500px;
  position: relative;
    background: #343434
}
#infoi {
  width: 100px;
  height: 100px;
  position: absolute;
  bottom: 35px;
  left: 10px;
}
#infoi {
  z-index:10000; 
}

Get x-axis value in Highcharts


In this example we get the corresponding latest x-axis value of the max data in a y-axis series in Highcharts.

Here's the code below with comments:

$(function () {
    $('#container').highcharts({
        xAxis: {
            categories: ['a', 'b', 'c', 'd', 'e', 'f']
        },
        series: [{
            data: [5, 16, 10, 3, 12, 16]
        }, {
            data: [11, 18, 15, 16, 18, 11]
        }]
    });


    $("#click").click(function () {
        var chart = $("#container").highcharts(),
            series,
            i = 0,
            arr = [],
            myIndex = [],
            //change the index of the series that you like to get
            s = chart.series[1],

            max = s.dataMax,
            len = s.data.length;

        //getting the index with max value in y-axis
        for (var j = 0; j < len; j++) {
            arr[j] = s.data[j].y;
            if (arr[j] === max) {
                myIndex.push(j);
            }
        }
        //get the max of the indices
        var maxIndex = Math.max.apply(Math, myIndex);
        console.log(myIndex);
        $("#report").html("x: " + chart.xAxis[0].categories[maxIndex] + ", y: " + max);
    });
});

Scribble

Just some random thoughts when I was sick written in a pad paper decided to wrote it here.

Quote

You read a quote
You lived with it
That's wrong!

You read a quote
You looked for the author
Studied his life

You read a quote
You are relieved
Why?

You read a quote
You approved
Because it suits you
-----------
My love for you
is not that strong.
I don't think it's not true.
I don't think it's not real.
But it's love.
-------------

Note to Self:
Take care of my heart (I'll change my way of meeting new people,)
I'll save now. (I've been sick lately.)
I will listen to my mother more. (She always takes good care of me.)
Look for an ounce of confidence and drink it.
Less internet usage after work.


What's the point of seeing someone who doesn't want to be in a relationship?
I do missed her.


You know what's hard?
It's accepting that you have been rejected by the person you loved.
You have to move on, you need to move on.
It eats up you happiness, it hurts.
It stays and wanted to be felt;pain.

~fin

Oh CORS!

Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources (e.g. fonts, JavaScript, etc.) on a web page to be requested from another domain outside the domain from which the resource originated.-Wikipedia
Because I'm trying to get or access data from another site, I have encountered this error:

“No 'Access-Control-Allow-Origin' header is present on the requested resource”

After spending bunch of hours reading what really causes it, finally found a solution. HAHA

CORS Anywhere is a NodeJS proxy which adds CORS headers to the proxied request.

//this is to allow Cross-Origin Resource Sharing
jQuery.ajaxPrefilter(function (options) {
    if (options.crossDomain && jQuery.support.cors) {
        options.url = 'https://cors-anywhere.herokuapp.com/' + options.url;
    }
});
$.ajax({
    url: <URL HERE>,
    dataType: 'json',
    type: "GET",
    success: function (e) {
    ....
    }
    ....

URL will be https://cors-anywhere.herokuapp.com/<URL HERE> in every request.
Credits to the person who created the script.

Search Text in Paragraph using jQuery


The code below highlight the words in the paragraph if it matches on the inputted keywords or text from the user.
  • Gets the value from the text box
  • Split if the words are separated by space
  • Store the values in an array
  • Pass those values in the function
  • and use RegExp to evaluate
  • If found, replaces the text with added span tag for the highlight.

$.fn.wrapInTag = function (opts) {
    var words = opts.words || [],
        regex = RegExp(words.join('|'), 'gi'),
        replacement = '<span class="highlight">$&</span>';
    
    return this.html(function () {
        return $(this).text().replace(regex, replacement);
    });
};


$('#terms').keyup(function () {
    var keywords = [];
    keywords = $(this).val().split(" ");
    $('p#text-body').wrapInTag({
        words: keywords
    });
});

Create Graph using Highcharts from a CSV File

1. Add these JavaScript inclusions in the head of your page

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script><script type="text/javascript" src="http://code.highcharts.com/highcharts.js"></script>

2. Add the JavaScript to initialize the chart on document ready

$(document).ready(function () {
    var options = {
        chart: {
            renderTo: 'container',
            type: 'line',
            width: 800,
            height: 450
        },
        title: {
            text: 'Cabadbaran, Agusan del Norte'
        },
        subtitle: {
            text: 'Source:CSU Phil-LiDAR 1',
            x: -20
        },
        xAxis: {
            categories: [],
            minTickInterval: 15,
            TickInterval: 15,
            tickmarkPlacement: "on",
            labels: {
                padding: 10,
                align: "center",
                style: {
                    fontSize: "10px"
                }
            }
        },
        yAxis: [{ //primary y axis 
            min: 0,
            max: 50,
            title: {
                text: "Rainfall Intensity, mm/hr."
            },
            reversed: !0,
            plotLines: [{
                value: 0,
                width: 1,
                color: "#808080"
            }],
            plotBands: [{
                color: '#86e3e7',
                from: 0,
                to: 2.5,
                label: {
                    text: 'Light',
                    align: 'left',
                    x: 10
                }
            }, {
                color: '#8aa7fd',
                from: 2.5,
                to: 7.5,
                label: {
                    text: 'Moderate',
                    align: 'left',
                    x: 10
                }
            }, {
                color: '#8686dc',
                from: 7.5,
                to: 15,
                label: {
                    text: 'Heavy',
                    align: 'left',
                    x: 10
                }
            }, {
                color: '#fed88d',
                from: 15,
                to: 30,
                label: {
                    text: 'Intense',
                    align: 'left',
                    x: 10
                }
            }, {
                color: '#fe9686',
                from: 30,
                to: 100,
                label: {
                    text: 'Torrential',
                    align: 'left',
                    x: 10
                }
            }]
        }, { //secondary y axis 
            max: 10,
            min: 0,
            title: {
                text: "Accumulated Rainfall, mm"
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: "#808080"
            }],
            opposite: !0,
            reversed: !1
        }],
        gridLineDashStyle: 'solid',
        series: []
    };
    $.get('https://dl.dropboxusercontent.com/u/75734877/AGUSAN_DEL_NORTE-CABADBARAN-RAIN2-.csv', function (data) {
        var lines = data.split('\n');
        options.series.push({
            name: "Rainfall Intensity",
            data: [],
            tooltip: {
                valueSuffix: "  mm/hr."
            },
            color: "#0000ff"
        }, {
            name: "Accumulated Rainfall",
            data: [],
            tooltip: {
                valueSuffix: " mm"
            },
            yAxis: 1,
            color: "#ff0000"
        });
        $.each(lines, function (lineNo, line) {
            var items = line.split(',');
            if (lineNo > 0) {
                $.each(items, function (itemNo, item) {
                    if (itemNo === 0) {
                        options.xAxis.categories.push(item);
                    } else if (itemNo === 2) {
                        options.series[0].data.push(parseFloat(item));
                    } else if (itemNo === 3) {
                        options.series[1].data.push(parseFloat(item));
                    }
                });
            }
        });
        var chart = new Highcharts.Chart(options);
    });
});

3. Add the container

<div id="container" style="width: 800px; height: 450px; margin: 0 auto; border: 2px solid #343434;border-radius:5px"></div> 

I also made some quite styling before the chart is loaded.

#container {
    background-image: url('hex-loader.gif');
    background-repeat:no-repeat;
    background-position:center center;
}

Demo

The code is based on this JSFiddle with a little modification to suit what I want.

Schedule Loading of Shapefile into a PostgreSQL Database

The code below automatically loads the shapefile found in a certain directory into a PostgreSQL database within a given interval(in this example 2 minutes).

Downside (in which I'm trying to figure out):
What if the filename of the shapefile changes?

Anyway, this suits of what I need right now.

__author__ = 'Matt'
import os
from django.db import connection
from django.contrib.gis.utils import LayerMapping
from .models import FloodHazard
import datetime
import time
import logging
from apscheduler.scheduler import Scheduler

logging.basicConfig()
# Start the scheduler
sched = Scheduler()
sched.daemonic = False
sched.start()

#ogrinspect evidensapp/data/flood_hazard/FloodHazard.shp FloodHazard --srid=32651 --mapping --multi
# Auto-generated `LayerMapping` dictionary for FloodHazard model
floodhazard_mapping = {
    'hazard': 'Hazard',
    'date_field': 'Date_',
    'geom': 'MULTIPOLYGON'
}

bound_shape = os.path.abspath(os.path.join(os.path.dirname(__file__),
                                           'data/flood_hazard/FloodHazard.shp'))
exist = os.path.isfile(bound_shape)

if exist:
    def run(verbose=True):
        try:
            cursor = connection.cursor()
            cursor.execute("TRUNCATE TABLE evidensapp_floodhazard RESTART IDENTITY")
            lm = LayerMapping(FloodHazard, bound_shape, floodhazard_mapping,
                              transform=False, encoding='iso-8859-1')
            lm.save(strict=True, verbose=verbose)
            print(datetime.datetime.now())
            print(exist)
            time.sleep(60)

        except FloodHazard.DoesNotExist:
            lm = LayerMapping(FloodHazard, bound_shape, floodhazard_mapping,
                              transform=False, encoding='iso-8859-1')
            lm.save(strict=True, verbose=verbose)
            print(datetime.datetime.now())
            time.sleep(60)

    # Schedules job_function to be run every 2 minutes
    sched.add_interval_job(run, minutes=2)

else:
    print(exist)
    sched.shutdown()

Change the model name and path/directory. As you noticed that if the table has an existing rows, it performed a TRUNCATE query to save memory and the system that I'm developing need the latest Flood Hazard Map. And also, it gives an error if you load a shapefile on the table with existing rows (Why?).

Next task to do is, check if the file has been modified otherwise stop the schedule.

This is based on this question and using Advanced Python Scheduler and LayerMapping utility of Django.