/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* eslint-disable array-element-newline */

'use strict';

var discreteUniform = require( '@stdlib/random/base/discrete-uniform' );
var normal = require( '@stdlib/random/base/normal' ).factory;
var ndarray = require( '@stdlib/ndarray/ctor' );
var Float64Array = require( '@stdlib/array/float64' );
var incrkmeans = require( './../lib' );

var clusters;
var results;
var randn;
var ctor;
var acc;
var N;
var k;
var c;
var v;
var X;
var Y;
var x;
var y;
var i;

// Define the number of data points to simulate:
N = 1e4;

// Define the number of clusters:
k = 5;

// Define cluster properties:
ctor = ndarray( 'float64', 2 );
clusters = new Float64Array([
	0.0, 1.0, 0.0, 1.0, // meanX, stdevX, meanY, stdevY
	-5.0, 1.0, 5.0, 1.0,
	5.0, 1.0, 5.0, 1.0,
	5.0, 1.0, -5.0, 1.0,
	-5.0, 1.0, -5.0, 1.0
]);
clusters = ctor( clusters, [ k, 4 ], [ 4, 1 ], 0, 'row-major' );

// Initialize a 2-dimensional k-means accumulator:
acc = incrkmeans( k, 2, {
	'metric': 'euclidean',
	'init': [ 'kmeans++', 100 ]
});

// Create PRNGs for generating pseudorandom numbers drawn from 2-d uncorrelated normal distributions...
ctor = ndarray( 'generic', 2 );
randn = ctor( new Array( k*2 ), [ k, 2 ], [ 2, 1 ], 0, 'row-major' );
for ( i = 0; i < k; i++ ) {
	randn.set( i, 0, normal( clusters.get( i, 0 ), clusters.get( i, 1 ) ) );
	randn.set( i, 1, normal( clusters.get( i, 2 ), clusters.get( i, 3 ) ) );
}

// Create a 2-d vector for storing simulated data:
ctor = ndarray( 'float64', 1 );
v = ctor( new Float64Array( 2 ), [ 2 ], [ 1 ], 0, 'row-major' );

// Simulate data points and incrementally perform k-means clustering...
X = [];
Y = [];
for ( i = 0; i < N; i++ ) {
	// Pick a random cluster from which to sample:
	c = discreteUniform( 0, k-1 );

	// Generate a random cluster data point:
	x = randn.get( c, 0 )();
	v.set( 0, x );
	X.push( x );

	y = randn.get( c, 1 )();
	v.set( 1, y );
	Y.push( y );

	// Update the accumulator:
	acc( v );
}

// Print cluster results:
results = acc();
for ( i = 0; i < k; i++ ) {
	console.log( 'Cluster %d', i+1 );
	console.log( '  centroid: (%d, %d)', results.centroids.get( i, 0 ), results.centroids.get( i, 1 ) );
	console.log( '  size: %d', results.stats.get( i, 0 ) );
}

@@ -977,16 +977,28 @@
 esults;%0A
+var totals;%0A
 var rand
@@ -1010,16 +1010,26 @@
 r ctor;%0A
+var opts;%0A
 var acc;
@@ -1503,136 +1503,182 @@
 %0A// 
-Initialize a 2-dimensional k-means accumulator:%0Aacc = incrkmeans( k, 2, %7B%0A%09'metric': 'euclidean',%0A%09'init': %5B 'kmeans++', 100 %5D%0A%7D
+Define accumulator options:%0Aopts = %7B%0A%09'metric': 'euclidean',%0A%09'init': %5B 'kmeans++', 100 %5D%0A%7D;%0A%0A// Initialize a 2-dimensional k-means accumulator:%0Aacc = incrkmeans( k, 2, opts 
 );%0A%0A
@@ -2283,16 +2283,44 @@
 ring...%0A
+totals = %5B 0, 0, 0, 0, 0 %5D;%0A
 X = %5B%5D;%0A
@@ -2434,16 +2434,35 @@
 , k-1 );
+%0A%09totals%5B c %5D += 1;
 %0A%0A%09// Ge
@@ -2640,16 +2640,26 @@
 lator:%0A%09
+results = 
 acc( v )
@@ -2706,16 +2706,54 @@
  acc();%0A
+if ( results ) %7B%0A%09console.log( '' );%0A%09
 for ( i 
@@ -2768,24 +2768,25 @@
  k; i++ ) %7B%0A
+%09
 %09console.log
@@ -2804,24 +2804,25 @@
 %25d', i+1 );%0A
+%09
 %09console.log
@@ -2911,16 +2911,17 @@
  1 ) );%0A
+%09
 %09console
@@ -2965,14 +2965,145 @@
 ( i, 0 ) );%0A
+%09
 %7D%0A
+%09console.log( '' );%0A%7D%0A%0Aconsole.log( '' );%0Aconsole.log( 'True cluster distribution: %25s', totals.join( ', ' ) );%0Aconsole.log( '' );%0A

Print the true cluster distribution