Angular 2 : Data Bindings

Angular provides many kinds of data binding

We can group all bindings into three categories by the direction in which data flows. Each category has its distinctive syntax:


Any property in Component class can be shown as text through Interpolation written as {{}}

Property Binding

It is similar to Interpolation but it is a preferable way of doing one way binding, especially in case of styles and attribute bindings. It has a syntax []

Event Binding

It binds and event to a Component function. The events are standard browser events such as Click, DoubleClick etc.

Two-way binding

It binds a Component property to an input element. The changes gets reflected in the property at the same time. This is actually a combination of One-way binding and Event-binding. It is written as Banana-in-a-box syntax [(..)]. The outer braces shows One-way binding and the inner brace shows Event binding.

To Visualize


Interpolation : {{someText}}
Property Binding :
<img [src]='prop.URL'>
Event Binding :
<button (click)='showImage()'>
Two way Binding :
<input [(ngModel)]='Name'>



<input type="text" [value]="myName">
<button (click)="colorChange(textColor)" [style.color]="textColor">Change My Color</button>
<input type="text" [(ngModel)]="textColor">

<table border=2>
    <!--  expression calculates colspan=2 -->
        <td [attr.colspan]="1 + 1 + 1">Left - Center - Right</td>

Live Code 

Plunker here:,preview

Genetic Algorithms - An Introduction

Genetic algorithms are one of the best ways to solve a problem for which little is known. They are a very general algorithm and so will work well in any search space. All you need to know is what you need the solution to be able to do well, and a genetic algorithm will be able to create a high quality solution. Genetic algorithms use the principles of selection and evolution to produce several solutions to a given problem.

When are Genetic Algorithms Useful?

There are at least three situations where genetic algorithms are useful:

The objective function is not smooth (i.e., not differentiable).
There are multiple local optima.
There is a large number of parameters (the meaning of "large" keeps changing).

A typical genetic algorithm requires:

1) A genetic representation (e.g. Array of Bits) of the solution domain,
2) A fitness function to evaluate the solution domain. A fitness function is a particular type of objective function that is used to summarize, as a single figure of merit, how close a given design solution is to achieving the set aims.

Once the genetic representation and the fitness function are defined, a GA proceeds to initialize a population of solutions and then to improve it through repetitive application of the mutation, crossover, inversion and selection operators.

Simple Genetic Algorithm Pseudo-code
function SimpleGeneticAlgorithm ()
 Initialize population;
 Calculate fitness function;
 While (fitness value != termination criteria)
  Calculate fitness function;

Genetic Algorithms steps:

1. Initialization 

The population size depends on the nature of the problem, but typically contains several hundreds or thousands of possible solutions. Often, the initial population is generated randomly, allowing the entire range of possible solutions (the search space). Occasionally, the solutions may be "seeded" in areas where optimal solutions are likely to be found.

2. Selection

During each successive generation, a portion of the existing population is selected to breed a new generation. Individual solutions are selected through a fitness-based process, where fitter solutions (as measured by a fitness function) are typically more likely to be selected. The fitness function is defined over the genetic representation and measures the quality of the represented solution. The fitness function is always problem dependent.

3. Genetic operators

The next step is to generate a second generation population of solutions from those selected through a combination of genetic operators: crossover (also called recombination), and mutation.

a) Crossover (also called as Recombination)

Crossover is a genetic operator used to vary the programming of a chromosome or chromosomes from one generation to the next. It is analogous to reproduction and biological crossover, upon which genetic algorithms are based. Cross over is a process of taking more than one parent solutions and producing a child solution from them.

Single-point crossover

Two-point crossover

Cut and splice

b) Mutation

Mutation alters one or more gene values in a chromosome from its initial state. In mutation, the solution may change entirely from the previous solution. Hence GA can come to a better solution by using mutation. Mutation should allow the algorithm to avoid local minima by preventing the population of chromosomes from becoming too similar to each other, thus slowing or even stopping evolution.
The mutation of bit strings ensue through bit flips at random positions.
1 0 1 0 0 1 0
1 0 1 0 1 1 0

4. Termination

This generational process is repeated until a termination condition has been reached. Common terminating conditions are:
  • A solution is found that satisfies minimum criteria
  • Fixed number of generations reached
  • Allocated budget (computation time/money) reached
  • The highest ranking solution's fitness is reaching or has reached a plateau such that successive iterations no longer produce better results
  • Manual inspection
  • Combinations of the above

Case Study : Roulette Wheel Selection

Parents are selected according to their fitness. The better the chromosomes are, the more chances to be selected they have. Imagine a roulette wheel where all the chromosomes in the population are placed. The size of the section in the roulette wheel is proportional to the value of the fitness function of every chromosome - the bigger the value is, the larger the section is. See the following picture for an example.

A marble is thrown in the roulette wheel and the chromosome where it stops is selected. Clearly, the chromosomes with bigger fitness value will be selected more times.

This process can be described by the following algorithm.

[Sum] Calculate the sum of all chromosome fitnesses in population - sum S.
[Select] Generate random number from the interval (0,S) - r.
[Loop] Go through the population and sum the fitnesses from 0 - sum s. When the sum s is greater then r, stop and return the chromosome where you are. Of course, the step 1 is performed only once for each population.

Python code for Roulette wheel selection 

#!/usr/bin/env python

import sys, time, numpy, random

# Individual has a genome and fitness and knows how to print itself
class Individual:
    def __init__(self, genome):
        if genome is None:
            self.genome = numpy.array(numpy.random.random_integers(0, 1, LEN), dtype='bool')
            self.genome = genome = FITNESS(self.genome)
    def __str__(self):
        return "".join(str(int(i)) for i in self.genome)
# Uniform crossover
def xover(a, b):
    g, h = a.genome.copy(), b.genome.copy()
    for pt in range(len(g)):
        if numpy.random.random() < 0.5:
            g[pt], h[pt] = h[pt], g[pt]
    return (Individual(g), Individual(h))

# Per-gene bit-flip mutation
def mutate(a):
    g = a.genome.copy()
    for pt in range(len(g)):
        if numpy.random.random() < PMUT:
            g[pt] = not g[pt]
    return Individual(g)

# Print statistics, and return True if we have succeeded already.
def stats(pop, gen):
    best = max(pop, key=lambda x:
    print("{0} {1:.2f} {2} {3}".format(gen, numpy.mean([ for i in pop]),, str(best)))
    return ( >= SUCCESS_THRESHOLD)

# Roulette-wheel (fitness-proportionate) selection. Tricky but fast.
def roulette(items, n):
    total = float(sum( for w in items))
    i = 0
    w, v = items[0].fitness, items[0]
    while n:
        x = total * (1 - numpy.random.random() ** (1.0 / n))
        total -= x
        while x > w:
            x -= w
            i += 1
            w, v = items[i].fitness, items[i]
        w -= x
        yield v
        n -= 1

# Use many tournaments to get parents
def tournament(items, n, tsize=5):
    for i in range(n):
        candidates = random.sample(items, tsize)
        yield max(candidates, key=lambda x:

# Run one generation
def step(pop):
    newpop = []
    parents = SELECTION(pop, len(pop) + 1) # one extra for final xover    
    while len(newpop) < len(pop):
        if numpy.random.random() < CROSSOVER_PROB:
            # crossover and mutate to get two new individuals
            newpop.extend(map(mutate, xover(,
            # clone and mutate to get one new individual
    return newpop
def main():
    if len(sys.argv) > 1:
    pop = [Individual(None) for i in range(POPSIZE)]
    stats(pop, 0)
    for gen in range(1, GENERATIONS):
        pop = step(pop)
        if stats(pop, gen):

# parameters
SELECTION = roulette # roulette sucks: tournament is better


Print first repeating character of input string in C++ : Memory Optimized

#include <iostream>

#define CHAR_TO_INT(c) (c - 'a' + 1)
int main(int argc, char** argv)
    std::string strInput;
    std::cout << "Get any string:\t";
    std::cin >> strInput;
    int count = 0;

    for (int i = 0; i < strInput.length(); i++) {

        int val = CHAR_TO_INT(strInput[i]);
        if ((count & (1 << val)) > 0) {
            std::cout << "Input string has first non-uniques character \t" << strInput[i];
        count |= (1 << val);

    return 0;

Journey of AI in Robotics and Mobile Apps

In early age, use of AI was limited to the computers. Later on, robotics came into the picture.

In our day, it becomes an integral part of human life by expanding its technical proficiency for mobile platforms. Introducing highly intuitive apps, AI is changing the everyday lives of users profoundly.

* Here we go with the AI and Robotics evolution timeline *

Isolated Storage in Windows Desktop Apps using .Net

As we are becoming more and more aware of, giving programs unfettered access to a computer is not a great idea. Unfortunately, many programs still need to save some sort of state data about themselves. To bridge the needs of applications to save data and the desire of administrators and users to use more limited security settings, the .NET Framework supports the concept of isolated storage.

What Is Isolated Storage?

Running code with limited privileges has many benefits given the presence of predators who are foisting viruses and spyware on your users. The .NET Framework has several mechanisms for dealing with running as least-privileged users. By using isolated storage to save your data, you will have access to a safe place to store information without needing to resort to having users grant access to specific files or folders in the file system. The main benefit of using isolated storage is that your application will run regardless of whether it is running under partial, limited, or full-trust.

The IsolatedStorageFile Class

The IsolatedStorageFile class provides the basic functionality to create files and folders in isolated storage.

IsolatedStorageFile Static/Shared Methods

Name Description
GetMachineStoreForApplication Retrieves a machine-level store for calling the Click-Once,application
GetMachineStoreForAssembly Retrieves a machine-level store for the assembly that called
GetMachineStoreForDomain Retrieves a machine-level store for the AppDomain within the current,assembly that called.
GetStore Retrieves stores based on the IsolatedStorage- Scope enumerator
GetUserStoreForApplication Retrieves a user-level store for the Click-Once application that,called
GetUserStoreForAssembly Retrieves a user-level store for the assembly that called
GetUserStoreForDomain Retrieves a user-level store for the AppDomain within the current,assembly that called

How to Create a Store

Before you can save data in isolated storage, you must determine how to scope the data you want in your store. For most applications, you will want to choose one of the following two methods:


This method creates a store to keep information that is specific to the calling assembly and the local machine. This method is useful for creating application-level data.

IsolatedStorageFile machineStorage = IsolatedStorageFile.GetMachineStoreForAssembly();


This method creates a store to keep information that is specific to the calling assembly and the current user. This method is useful for creating user-level data. If you need to specify the user for the store, you will need to use impersonation.

IsolatedStorageFile userStorage = IsolatedStorageFile.GetUserStoreForAssembly();

Example Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.IsolatedStorage;

namespace ConfigurationStorage
    public partial class ConfigurationStorage : Form
        public ConfigurationStorage()

        private void ConfigurationStorage_Load(object sender, EventArgs e)
            comboBox_Car.Items.AddRange(new object[] {
                                                        "BMW","Mercitez Benz", "Honda Civic",
                                                        "Mistibushi Lancer", "Toyota Supra",
            comboBox_Color.Items.AddRange(new object[] { "Red", "Green", "Blue" });
            comboBox_HolDest.Items.AddRange(new object[] { "Singapore", "Paris", "Las Vegas", "Perl Harbour" });
            comboBox_Singer.Items.AddRange(new object[] { "Shakira Mabarak", "Enriquae Iglesias", "Eminem", "Snoop Dogg", "Shina Twain" });
            comboBox_Sports.Items.AddRange(new object[] { "Cricket", "Football", "Tennis", "WWE", "Hockey" });

            comboBox_Car.SelectedIndex = 0;
            comboBox_Color.SelectedIndex = 0;
            comboBox_HolDest.SelectedIndex = 0;
            comboBox_Singer.SelectedIndex = 0;
            comboBox_Sports.SelectedIndex = 0;


        private void button_Save_Click(object sender, EventArgs e)
            IsolatedStorageFile userStore = IsolatedStorageFile.GetUserStoreForAssembly();
            IsolatedStorageFileStream userStream = new IsolatedStorageFileStream("ConfigurationStorage_UserPreferences.settings", FileMode.Create, userStore);

            StreamWriter writer = new StreamWriter(userStream);
            writer.Write("Car:" + comboBox_Car.SelectedIndex.ToString() + "," +
                         "Color:" + comboBox_Color.SelectedIndex.ToString() + "," +
                         "HolidayDestination:" + comboBox_HolDest.SelectedIndex.ToString() + "," +
                         "Singer:" + comboBox_Singer.SelectedIndex.ToString() + "," +
                         "Sports:" + comboBox_Sports.SelectedIndex.ToString() + ",");

        void CheckAndLoadPrefs()
            IsolatedStorageFile userStore = IsolatedStorageFile.GetUserStoreForAssembly();
            string[] files = userStore.GetFileNames("ConfigurationStorage_UserPreferences.settings");

            if(files.Length > 0)
                IsolatedStorageFileStream userStream = new IsolatedStorageFileStream("ConfigurationStorage_UserPreferences.settings", FileMode.Open, userStore);
                StreamReader reader = new StreamReader(userStream);

                string data = reader.ReadToEnd();

                int pos = 0;
                int colonpos = 0;
                int commapos = -1;
                string userObject = "";
                string indexStr = "";
                foreach (char c in data)
                    if (c == ':')
                        colonpos = pos;
                        userObject = data.Substring(commapos + 1, colonpos - commapos - 1);                                               
                    if (c == ',')
                        commapos = pos;
                        indexStr = data.Substring(colonpos + 1, commapos - colonpos -1);
                        int index = Int32.Parse(indexStr);
                        if (userObject == "Car")
                            comboBox_Car.SelectedIndex = index;
                        else if (userObject == "Color")
                            comboBox_Color.SelectedIndex = index;
                        else if (userObject == "HolidayDestination")
                            comboBox_HolDest.SelectedIndex = index;
                        else if (userObject == "Singer")
                            comboBox_Singer.SelectedIndex = index;
                        else if (userObject == "Sports")
                            comboBox_Sports.SelectedIndex = index;

File compression using C#.Net

Follow 3 simple steps:

1. Add a new .cs file in your project and add the below namespaces.

using System.IO;
using System.IO.Compression;

2. Add the below code; use this function for compressing the file.

static void CompressFile(string inFileName, string outFileName)
     FileStream sourceFile = File.Open(inFileName, FileMode.Open);
     FileStream destFilename = File.Open(outFileName, FileMode.Create);

     GZipStream compStream = new GZipStream(destFilename, CompressionMode.Compress);
     Byte[] buffer = new Byte[1024*1024];
     int tempByte = sourceFile.Read(buffer,0,buffer.Length);
     while (tempByte > 0)
          compStream.Write(buffer, 0, buffer.Length);
          tempByte = sourceFile.Read(buffer, 0, buffer.Length);

3. Add the below code; use this function for uncompressing the file.

static void UnCompressFile(string inFileName, string outFileName)
     FileStream sourceFile = File.Open(inFileName, FileMode.Open);
     FileStream destFilename = File.Open(outFileName, FileMode.Create);

     GZipStream compStream = new GZipStream(destFilename, CompressionMode.Decompress);
     int tempByte = compStream.ReadByte();
     while (tempByte != -1)
     {    destFilename.WriteByte((Byte)tempByte);
          tempByte = compStream.ReadByte();

Programming Superstars

This blog is dedicated to our "Programming Heroes" who have lead the evolution of Information Technology, programming languages and libraries in such a way that these have become the real I.T. game changers.

While these technological evolution and revolutions are endless process, we must thank to those who always took initiatives to take the current development technologies to a next level.

Here is a list of some:

1. Anders Hejlsberg

Image Source :

Creator and Lead architect of C# language and core developer on TypeScript.

Top Video

2. James Arthur Gosling

Image Source :

Creator of Java programming language and best known as the father of the Java programming language.

Top Video

3. John Resig

Image Source :

Creator and Lead developer of JQuery.

Top Video

4. Ryan Dahl

Image Source :

Creator of NodeJs - An open-source, cross-platform JavaScript runtime environment for developing a diverse variety of tools and applications.

Top Video

5. Terence Parr

Image Source :

Creator of ANTLR (ANother Tool for Language Recognition).

Top Video

6. Jared Hanson

Image Source :

Creator of PassportJS - Passport is authentication middleware for Node.js.

Top Video

7. Guido van Rossum

Image Source :

Van Rossum is Python's principal author, and his continuing central role in deciding the direction of Python is reflected in the title given to him by the Python community, benevolent dictator for life (BDFL).

Top Video

We will be adding more stars to the sky...:)

Significant SQL Server Queries

Converting XML to Table

WITH cte 
     AS (SELECT Cast(expression AS XML) AS Expression 
         FROM   [table name] 
         WHERE  id = 109) 
SELECT p.value('@targetField', 'varchar(max)')      AS TargetField, 
       p.value('@sourceExpression', 'varchar(max)') AS SourceField 
FROM   cte 
       CROSS apply expression.nodes('/parentNode/childNode') t(p) 

Check which all Tables contains a particular column

SELECT t.NAME                 AS table_name, 
       Schema_name(schema_id) AS schema_name, 
       c.NAME                 AS column_name 
FROM   sys.tables AS t 
       INNER JOIN sys.columns c 
               ON t.object_id = c.object_id 
WHERE  c.NAME LIKE '%ColumnName%' 
ORDER  BY schema_name, 

Cached query inspector

The purpose of this query is to check the query plan cache for large queries
and gives you the execution plan for each query.

SELECT refcounts     AS 'Reference_Counts', 
       size_in_bytes AS 'Size_in_bytes', 
       cacheobjtype  AS 'Cache_type', 
       st.encrypted  AS 'Is_encrypted_text', 
       text          AS 'SQL_text', 
       query_plan    AS 'Query_plan' 
FROM   sys.dm_exec_cached_plans cp WITH (nolock) 
       CROSS apply sys.Dm_exec_sql_text(cp.plan_handle) st 
       CROSS apply sys.Dm_exec_query_plan(cp.plan_handle) qp 
ORDER  BY refcounts DESC, 
          size_in_bytes DESC 

Current Locks with Execution Plan

The purpose of this query is to see what queries are currently holding locks and gives you the execution plan for the blocking and executing queries.

SELECT Db_name(locks.resource_database_id)  AS 'Database', 
       locks.request_status                 AS 'Status', 
       bs.host_name                         AS 'Blocking_host', 
       bs.nt_domain + '\' + bs.nt_user_name AS 'Blocking_user', 
       tasks.wait_duration_ms / 1000.       AS 'Current_wait_duration_seconds', 
       blockText.text                       AS 'Blocking_sql_text', 
       blockPlan.query_plan                 AS 'Blocking_query_plan', 
       blockText.text                       AS 'Executing_sql_text', 
       blockPlan.query_plan                 AS 'Executing_query_plan', 
       locks.resource_type                  AS 'Resource_type', 
       locks.resource_subtype               AS 'Resource_sub_type', 
       locks.resource_description           AS 'Resource_description', 
       locks.request_mode                   AS 'Request_mode', 
       locks.request_type                   AS 'Request_type', 
       tasks.wait_type                      AS 'Wait_type' 
FROM   sys.dm_tran_locks locks WITH (nolock) 
       JOIN sys.dm_os_waiting_tasks tasks WITH (nolock) 
         ON locks.lock_owner_address = tasks.resource_address 
       JOIN sys.dm_exec_sessions bs WITH (nolock) 
         ON tasks.blocking_session_id = bs.session_id -- Blocking session 
       JOIN sys.dm_exec_requests br WITH (nolock) 
         ON br.session_id = tasks.blocking_session_id -- Blocking request 
       JOIN sys.dm_exec_sessions cs WITH (nolock) 
         ON tasks.session_id = cs.session_id -- Current session 
       JOIN sys.dm_exec_requests cr WITH (nolock) 
         ON cr.session_id = tasks.session_id -- Current request 
       CROSS apply sys.Dm_exec_sql_text(br.sql_handle) blockText 
       CROSS apply sys.Dm_exec_query_plan(br.plan_handle) blockPlan 
       CROSS apply sys.Dm_exec_sql_text(cr.sql_handle) currText 
       CROSS apply sys.Dm_exec_query_plan(cr.plan_handle) currPlan 

Currently running queries

The purpose of this query is to check to see what queries are currently running and gives you the execution plan for each query. It ignores any query that is on the current SQL connection.

SELECT req.session_id                         AS 'Session_ID', 
       Db_name(req.database_id)               AS 'Database_Name', 
       ses.host_name                          AS 'Executing_Host', 
       ses.nt_domain + '\' + ses.nt_user_name AS 'Executing_User', 
       req.command                            AS 'Command_Type', 
       req.status                             AS 'Command_Status', 
       ses.deadlock_priority                  AS 'Deadlock_Priority', 
       req.cpu_time                           AS 'CPU_Time', 
       req.total_elapsed_time                 AS 'Elapsed_Time', 
       sqltext.text                           AS 'SQL_Text', 
       query_plan                             AS 'Query_plan' 
FROM   sys.dm_exec_requests req WITH (nolock) 
       JOIN sys.dm_exec_sessions ses WITH (nolock) 
         ON req.session_id = ses.session_id 
       CROSS apply sys.Dm_exec_sql_text(sql_handle) sqltext 
       CROSS apply sys.Dm_exec_query_plan(plan_handle) qp 
WHERE  req.session_id <> @@SPID 
ORDER  BY req.total_elapsed_time DESC, 
          req.cpu_time DESC 

Virtual file statistics

- For data files, MS recommend: < 10 ms = Good | 10 - 20 ms = Acceptable | > 20 ms = Unacceptable
- For log files, MS recommend: < 5 ms = Good | 5 - 15 ms = Acceptable | > 15 ms = Unacceptable

SELECT Db_name(database_id)                       AS 'Database_Name', 
         WHEN file_id = 2 THEN 'Log' 
         ELSE 'Data' 
       END                                        AS 'File_Type', 
       ( ( size_on_disk_bytes / 1024 ) / 1024.0 ) AS 'Size_On_Disk_in_MB', 
       io_stall_read_ms / num_of_reads            AS 'Avg_Read_Transfer_in_Ms', 
         WHEN file_id = 2 THEN 
             WHEN io_stall_read_ms / num_of_reads < 5 THEN 'Good' 
             WHEN io_stall_read_ms / num_of_reads < 15 THEN 'Acceptable' 
             ELSE 'Unacceptable' 
             WHEN io_stall_read_ms / num_of_reads < 10 THEN 'Good' 
             WHEN io_stall_read_ms / num_of_reads < 20 THEN 'Acceptable' 
             ELSE 'Unacceptable' 
       END                                        AS 'Average_Read_Performance', 
       io_stall_write_ms / num_of_writes          AS 'Avg_Write_Transfer_in_Ms', 
         WHEN file_id = 2 THEN 
             WHEN io_stall_write_ms / num_of_writes < 5 THEN 'Good' 
             WHEN io_stall_write_ms / num_of_writes < 15 THEN 'Acceptable' 
             ELSE 'Unacceptable' 
             WHEN io_stall_write_ms / num_of_writes < 10 THEN 'Good' 
             WHEN io_stall_write_ms / num_of_writes < 20 THEN 'Acceptable' 
             ELSE 'Unacceptable' 
       END                                        AS 'Average_Write_Performance' 
FROM   sys.Dm_io_virtual_file_stats(NULL, NULL) 
WHERE  num_of_reads > 0 
       AND num_of_writes > 0 

Wait statistics finder

WITH waits 
     AS (SELECT wait_type                       AS 'Wait_type', 
                wait_time_ms / 1000.0           AS 'Wait_time_seconds', 
                100.0 * wait_time_ms / Sum(wait_time_ms) 
                                         OVER() AS 'Percent_of_results', 
                    ORDER BY wait_time_ms DESC) AS 'Row_number' 
         FROM   sys.dm_os_wait_stats WITH (nolock) 
                                   'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 
                                   'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 
                                   'ONDEMAND_TASK_QUEUE', 'BROKER_EVENTHANDLER', 
                                           'SLEEP_BPOOL_FLUSH' )) 
SELECT W1.wait_type                                       AS 'Wait_Type', 
       Cast(W1.wait_time_seconds AS DECIMAL(12, 2))       AS 'Wait_time_seconds' 
       Cast(W1.percent_of_results AS DECIMAL(12, 2))      AS 
       Cast(Sum(W2.percent_of_results) AS DECIMAL(12, 2)) AS 
FROM   waits AS W1 
       INNER JOIN waits AS W2 
               ON W2.[row_number] <= W1.[row_number] 
GROUP  BY W1.[row_number], 
HAVING Sum(W2.percent_of_results) - W1.percent_of_results < 99 
OPTION (recompile)