Making IsThisTaxiLegal–thinking about Proof of Concept

It can be improved so many ways:

  1. Making OCR ( to recognize the plates number)
  2. Making application Android / iPhone
  3. Making Windows (Store ) application ( not really necessary, but anyway)
  4. Finding if another cities have taxi licenses available
  5. Publicity
  6. Improving with ratings for taxi drivers
  7. Find a lawyer that knows what to do next
  8. Improving the documentation
  9. Passing from csv to sql lite
  10. Downloading automatically the pdf with licences from www.pmb.ro/adrese_utile/transport_urban/autorizatii_taxi/autorizatii_TAXI.php
  11. Making all this points on https://github.com/ignatandrei/IsThisTaxiLegal as issues
  12. Running the test automatically

And it is a small application!

If someone wants to help / or come with new ideas, p[lease leave a message here or on https://github.com/ignatandrei/IsThisTaxiLegal

Making Is This Taxi Legal–Proof of concept

This werer the steps for making a Proof of concept for Is This Taxi Legal application http://isthistaxilegal.apphb.com

Finding PDF about taxi licence for Bucuresti : PDF at http://www.pmb.ro/adrese_utile/transport_urban/autorizatii_taxi/autorizatii_TAXI.php

Thinking about application + web site about this -with a simple search and possible OCR ( take image of the car plate and recognizing number) . Also for international ( GPS for phones to know the city). Also IOT for monitoring the illegal taxi movement( could be also illegal to do this)

The Proof of Concept: A WebAPI + WebSite( that can be accessed also by mobile) to enter a plate number and find if it is legal. Maybe later an Android App.

Step 1 : acquiring data from http://www.pmb.ro/adrese_utile/transport_urban/autorizatii_taxi/autorizatii_TAXI.php

. Download situatia_autorizatiilor_taxi_20171208.PDF

Step 2 : cleaning data – read with Word and transform into CSV.

Trying <table>. ConvertToText – not good, it preserves the return character and data can not be read safely after that.

The solution: read row by row and replace CR/LF with empty for each cell.

After this, problem with Bell character – replace this also the 7 character

After this, problem with repeating headers for each table in the csv

This is the VBA code

( maybe doing same in R : https://datascienceplus.com/extracting-tables-from-pdfs-in-r-using-the-tabulizer-package/ )

Step 3 : Making objects to support

First creating objects to support this . Car, City, LicenseState, Licensee, TaxiAutorization.

Creating test – the City should be unique – even if Bucarest is multiple times, the City object should be the same.

Step 4: Consolidating data from CSV to objects

Creating objects to mimic CSV data . Return to step 2 and put separator | instead of ,

Problem with parsing data

– a date could not exist, so it will be nullable

– could be either dd.mm.yyyy , either d.mm.yyyy either 27.02.202

Separate the lines with errors from the lines without errors . And return the result as a tuple

Making test in order to see the errors

Step 5: Application Web + WebAPI to display data

Making WEBAPI for seeing all and some taxis

See that valid taxis are not parsed correctly ( Validat vs Valid) . Modify test

Discover there are some licenses with state…

Step 6: Deploy sources to GitHub

Easy to do – create and submit at https://github.com/ignatandrei/IsThisTaxiLegal

Step 7: Create an application visible on internet

You can create an account at appharbor.com , integrate with GitHub and deploy there : http://isthistaxilegal.apphb.com

 

Step 8: Document the API

Swagger / Swashbuckle is the easy way to do this. Deployed at http://isthistaxilegal.apphb.com/swagger/

Step 9 : Remake the documentation

Mention all the documentation in all places ( API, GitHub, others)

Mention the contact name if something is wrong

Add API for enums

 

This was a work of 8 hours –  and it is just a proof of concept .

AOP with Roslyn–part 5 – getting line number right

There is a problem with inserting lines  – the number of lines is not the same. What I mean by this?

Look at this example

 

 

using System;
namespace Test1
{
    class Program
    {
        static void Main(string[] args)
        {
              var dt=DateTime.Now;
        }
     }
}

 

The DateTime.Now is on line 8

When we insert lines before and after each method, the DateTime.Now is on line 9

using System;
namespace Test1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(" + "\"start Program_Main_6\"" + @");
            var dt = DateTime.Now;
            Console.WriteLine(" + "\"end Program_Main_6\"" + @");
        }
    }
}

This is usually not so important  – until you think about exception and stack trace. If we are moving the number of lines like so, the stack trace that will be raised by the program will make no sense to the programmer that grabs the code from the source control. More, the problem is aggravating with each method – so, if you have 30 methods in a file(I exaggerate a bit ) the number of lines will be increased with 30 for the last method. For others , will be with 29, 28 and so on, until the first method.

Fortunately, there is a solution – the #line directive.

See https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-line and  https://blogs.msdn.microsoft.com/abhinaba/2005/10/10/c-fun-with-line-directive/

So, what we need is to generate the #line <number> directive.

 

 

AOP with Roslyn–part 4–custom code to the end of the method

 

A good AOP needs also custom code to the beginning and to the end of the method. So we need to add formatter for the last line.

That means that the MetodRewriter constructor will look like this:

 

public MethodRewriter(string formatterFirstLine,string formatterLastLine=null)
{
   FormatterFirstLine = formatterFirstLine;
   FormatterLastLine = formatterLastLine;
}

 

More, we should put code at the beginning and at the end of the method

if (cmdLastLine!= null)
 blockWithNewStatements = blockWithNewStatements.Insert(0, cmdLastLine);
//code
if(cmdFirstLine != null)
 blockWithNewStatements = blockWithNewStatements.Insert(0, cmdFirstLine);

And the test will make the sentence

var dt=DateTime.Now;

between start and end lines:

[TestMethod]
 public void TestMethodRewriterLastLine()
 {

 var rc = new RewriteCode(
 formatterFirstLine: "Console.WriteLine(\"start {nameClass}_{nameMethod}_{lineStartNumber}\");",
 formatterLastLine: "Console.WriteLine(\"end {nameClass}_{nameMethod}_{lineStartNumber}\");"
 );
 rc.Code = @"
using System;
namespace Test1
{
 class Program
 {
 static void Main(string[] args)
 {
 var dt=DateTime.Now;
 }
 }
}";
 var result = rc.RewriteCodeMethod();
 var newCode = @"
using System;

namespace Test1
{
 class Program
 {
 static void Main(string[] args)
 {
 Console.WriteLine(" + "\"start Program_Main_6\"" + @");
 var dt = DateTime.Now;
 Console.WriteLine(" + "\"end Program_Main_6\"" + @");
 }
 }
}";
 Assert.AreEqual(result.Replace(Environment.NewLine, ""), newCode.Replace(Environment.NewLine, ""));
 }


 
 }

 

AOP with Roslyn–part 3–custom code at beginning of each method

Last time(http://msprogrammer.serviciipeweb.ro/2017/11/27/aop-with-roslynpart-2/)  we have injected a new code into each method . However, this code was pretty much hardcoded into the MethodRewriter class – it was a simple

Console.WriteLine(\”{nameClass}_{nameMethod}_{lineStartNumber}\”);

 

Now we want to can customize this code at the will of the programmer. For this, I have modified classes RewriteCode and MethodRewriter to accept a parameter named Formatter . To run the test that worked previously, I made a parameterless  constructor for RewriteCode in order to preserve compatiblity.

 

 

public RewriteCode(): this("Console.WriteLine(\"{nameClass}_{nameMethod}_{lineStartNumber}\");")
{

}
public RewriteCode(string formatter)
{
    Formatter = formatter;
}

 
The VisitMethod is now much simpler:

string nameVariable =Formatter.FormatWith(new { nameClass,nameMethod,lineStartNumber=lineStart.Line});
var cmd = SyntaxFactory.ParseStatement(nameVariable);

 
( The .FormatWith is an extension from https://github.com/crozone/FormatWith )
 
Also, I have made a new test to test this one – and I have inserted into code an variable named s:
 
string s=\”this is method {nameMethod} from class {nameClass} at line {lineStartNumber}\”;”
 
 
The test is

[TestMethod]
public void TestMethodRewriterAddVariable()
{

var rc = new RewriteCode(
"string s=\"this is method {nameMethod} from class {nameClass} at line {lineStartNumber}\";"
);
rc.Code = @"
using System;
namespace Test1
{
    class Program
    {
        static void Main(string[] args)
        {
              var dt=DateTime.Now;
        }
     }
}";
            var result = rc.RewriteCodeMethod();
            var newCode = @"
using System;

namespace Test1
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = ""this is method Main from class Program at line 6"";
            var dt = DateTime.Now;
        }
    }
}";
            Assert.AreEqual(result.Replace(Environment.NewLine, ""), newCode.Replace(Environment.NewLine, ""));
        }
    }