Friday, April 24, 2020

Swagger/Swashbuckle Kata

scratch
dotnet new webapi
dotnet add package swashbuckle.aspnetcore

Add code:
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddSwaggerGen(options => {
                options.SwaggerDoc("v1"new Microsoft.OpenApi.Models.OpenApiInfo());
            });
        }

Add more code:
            app.UseSwagger();
            app.UseSwaggerUI(options => {
                options.SwaggerEndpoint("v1/swagger.json""My API V1"); 
            });

Run it,
go here:
https://localhost:5001/swagger/index.html

Tuesday, April 21, 2020

browser-sync kata


mkdir one
cd one
new-fromtemplate html
npm install -g browser-sync
browser-sync start --server --files "*.html"

https://browsersync.io/

Terminalizer

 




https://github.com/faressoft/terminalizer


npm install -g terminalizer
terminalizer record demo
terminalizer render demo
 
 
The original gif was nearly 3 meg.  
 
 https://gifcompressor.com/
 
That took it down to 440K. Much better. 

Wednesday, January 1, 2020

Docker stuff

Some basic docker comamnds: sudo docker image list sudo docker run nginx sudo docker run hello-world sudo docker
sudo docker build -t myconsole2 . 
My first dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/core/runtime:3.1 AS runtime-env
WORKDIR /app
COPY --from=build-env /app/out . 
ENTRYPOINT [ "/app/console2" ]
docker exec --it {containerID} /bin/sh

Tuesday, December 24, 2019

Installing the .net sdk on a fresh install of Ubuntu Linux.

.Net is no longer a windows only programming framework. This is how to get things going on a fresh copy of linux.
Open a terminal window, then:
wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install apt-transport https
sudo apt-get install dotnet-sdk-3.1
The SDK allows you to build and run .net applications.
 
sudo apt-get install dotnet-runtime-3.1
The runtime merely allows you to run .net applications.
 
sudo apt-get install aspnetcore-runtime-3.1
Initially, I did the next commands through visual studio code, but it isn't necessary to use visual studio code to run them. Any terminal window will do.
dotnet new console
dotnet build 
dotnet publish
You will want to edit code eventually.
sudo snap install --classic code
Or just edit files in sublime
wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add -
echo "deb https://download.sublimetext.com/ apt/stable/" | sudo tee /etc/apt/sources.list.d/sublime-text.list
sudo apt-get update
sudo apt-get install sublime-text

Saturday, November 17, 2018

Composing multimaterial 3D objects with OpenSCAD and the command line

I'm a fan of OpenSCAD. I'm also a gardener. My sharpie based plant labels were becoming difficult to read after a season on the ground. Worse though, some of the plants that I keep in my bog garden were becoming completely unreadable. Especially since they can sit outdoors in soggy or wet acidic peat moss for years before I decide that I need to remind myself exactly which cultivar I am looking at. So, having recently acquired the Prusa MMU upgrade for MK3, I naturally decide to 3d print the labels, so that they will never fade, and it will indeed be impossible for them to do so, since the lettering will be in a completely different color of plastic. This brings us to the first bit of code, the 3d printable multi-material plant label written in OpenSCAD:
 
letter="<Main Text>";
smallText="<Small Text>";
    
length = 90;    
textStart = 0; 
height = 2; 

module GetText(bigText, littleText) { 
    union() {         
        translate([textStart, 0, 1.7])
            color("black", 1)
                linear_extrude(height=.301, convexity=4)
                    text(bigText, 
                    font="Bitstream Vera Sans",
                    halign="center",
                    size=7
                    );
        
        translate([textStart, -8, 1.7])
            color("black", 1)
                linear_extrude(height=.301, convexity=4)
                    text(littleText, 
                    font="Bitstream Vera Sans",
                    halign="center",
                    size=5// 3 is too small, doesn't extrude
                          // 4 is readable, but leaves gaps
                    );
            }
}

// First extrusion 
/*marker_one*/difference () { 
    color("white", 1.0)
        union() { 
            //stem
            translate([-length/2 - 100, -2, 0])
                cube([100, 4, height]);
            
            // tapered neck 
            linear_extrude(height) { 
                polygon(points=[[-length/2 -30, 0], [-length / 2, +10], [-length /2, -10], [-length / 2 - 30, 0]]);
            } 
            
            //Broad flat area for text
            translate([-length/2, -10, 0])
                cube([length, 20, height], center=false) ;
        }
    
    // holes for text 
    color("black", 1) 
        union() { 
            GetText(letter, smallText); 

            rotate([180, 0, 0])
                translate([textStart, 1, -2])
                    GetText(letter, smallText); 
        }
}

// Second Extrusion
/*marker_two*/union() { 
    GetText(letter, smallText); 

    rotate([180, 0, 0])
        translate([textStart, 1, -2])
            GetText(letter, smallText); 
}
With this file in hand, I first replace <Main Text> and <Small Text> with something appropriate for the label. I then replace /*marker_two*/ with an asterisk and export the object to an *.amf file. I then repeat the process with /*marker_one*/, after deleting the first asterisk. So I have two *.amf files which I will then load into slic3r and convert into gcode. I print a lot of these labels, and I only print one or two of each of them. So this turns out to be more labor intensive than I'd like. After some research, I created the following powershell function to do the work for me. All from a single command.
function Get-3dMMPlantLabel { 
    Param($mainText, $smallText="")
    process {
        $template = [System.IO.File]::ReadAllText("PlantLabelTemplate.scad")
        $output = $template.Replace("<Main Text>", $mainText).Replace("<Small Text>", $smallText)
        $outputOne = $output.Replace("/*marker_two*/", "*")
        $outputTwo = $output.Replace("/*marker_one*/", "*")
        $outputOneFileName = "$($mainText)1.scad"
        $outputTwoFileName = "$($mainText)2.scad"
    
        $outputOne | Out-File $outputOneFileName -Encoding ascii
        $outputTwo | Out-File $outputTwoFileName -Encoding ascii
    
        & "C:\Program Files\OpenSCAD\openscad.exe" -o "$($mainText)1.amf" $outputOneFileName
        & "C:\Program Files\OpenSCAD\openscad.exe" -o "$($mainText)2.amf" $outputTwoFileName
    
    }
}

Get-3dMMPlantLabel "Swamp Milkweed" "Somewhere in OH"
It outputs two files: "Swamp Milkweed1.amf" and "Swamp Milkweed2.amf" in this example. These are exactly what I need to orchestrate the 3d print in Slic3r. Now if only I could automate the gcode creation in Slic3r. Maybe next Saturday.

Monday, January 1, 2018

3d printing

I've dabbled in 3d printing for a few years now. I just got an awesome new Prusa Mk3. Love it.

I also started updating my OpenSCAD skills.

My latest creation is a simple flower pot.
The whole file on GitHub is here.

Some notes:
1) module -- this seems to be what I, as a programmer, would normal call a function. In the context of OpenSCAD they are modules. Not sure why the change in syntax, it's just something to remember.
2) for loops -- another new thing thing that I have learned, and an immensely useful one in this context.
3) hull() -- this is what I used to achieve the rounded edges. I'm not sure I grok it completely, but it is certainly another useful tool. Here is the article that led me to it.
4) GitHub has a great STL Viewer. The rendered object is here.
5) Oooh, and one more. The MCAD libraries are full of good stuff.
use <MCAD/--filename-->
To include them in a normal scad file.

Wednesday, October 4, 2017

Powershell, Adding Autocomplete to a Function

tldr: Add the ValidateSet attribute to a parameter. Like this: [ValidateSet("value 1", "value 2", "value etc")]$parameter or more verbosely:
function Get-Something(
    ValidateSet("value 1", "value 2", "value etc")]
    $parameter) {
    Write-Host "hi"
}
Just figured that out. Much bigger post here.

Tuesday, September 5, 2017

A tale of Mardown and browser based code editors.

I like Markdown. I want to use Markdown as much as possible. I also enjoy embedding LaTeX and graphs. I like using a chromebook.
First, I used visual studio and Mads’ Markdown editor extension for it. I usually had a copy or three of visual studio open so that didn’t matter much. But I started extending Markdown with my own javascript functions. I also started trying to embedd LaTeX.
An example of LaTeX:
\Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

Which renders as:

Then I found Markdown-plus which, is pretty awesome. I bought a copy. It works great in windows. I started writing LaTeX and graphs fluently. So I had to figure out a way to make it work on my chromebook. I started running Linux on it. Linux on a chromebook deserves a post or more in its own right. It is a very cool thing.
I got many things set up on the Linux-chromebook, and I learned many cool things. I pulled the markdown-plus code from GitHub and served it up to localhost. I learned how to start a web server from the command line. I learned how to use yarn, and npm. I started learning modern javascript functions and extensions, like ‘require’ and ‘let’, among others. I then forked the code and began dissecting it to see if I could add the “Save” functionality that would make it a viable tool on my chromebook. I ran into CodeMirror. I was awed by CodeMirror. I added “Save” capability, that seemed to be missing from markdown-plus. Perhaps the author didn’t want it competing with his 15$ windows app? Perhaps I was just missing something. Anyway, I created a pull request and called that piece done-ish. I now had a good flavor of Markdown running on my awesome chromebook. I was feeling pretty good about that.
However, then I ran into StackEdit. It is also open source on GitHub. It is also dissectable. From it I’ve been learning about even more javascript stacks. For its editor it uses prismjs. I also see Gulp, Bower, and some others that I’m not yet familiar with.
Anyway, so much awesome here, so little time. I’ll probably be abandoning markdown-plus in favor of StackEdit. Ahhh, there’s an easter egg here when you type ‘StackEdit’.
Written with StackEdit.

Sunday, September 3, 2017

Command Line web servers

The ability to serve up a random directory for http content is something that I learned quite recently. The first way that I did it:

Python3 -m http.server

From the angular cli, there is also:

ng-serve

And one more:

sudo npm install http-server -g
http-server


There are others as well, some of them are listed here:
Link to stackexchange

no need to run some heavyweight tool like IIS, Visual Studio, Apache, etc.

Monday, August 21, 2017

Fun with Angular and an HTML 5 canvas.

I updated my canvas-drawing post from 2014. Now it uses AngularJS instead of JQuery. Angular rocks.

Fiddle, GitHub

It doesn't embed well in blogger though.
The HTML: The javascript:

Wednesday, March 23, 2016

Don't use the 64 bit task manager to create a dump of a 32 bit process.

Yeah, that didn't work. The problem and the solution are both in the post title.

VS 2015 wouldn't let me look at the heap and didn't give me enough information about why, so I downloaded WinDbg and tried to get more information. At least with WinDbg I could make some progress.

New command: .cordll -ve -u -l

That gave me some good information, but it didn't work. What I did get from it was a path forward.

I ended up copying mscordacwks from the problem computer to the WinDbg directory on the computer that I was using for debugging. I also had to rename it to mscordacwks_AMD64_x86_4.0.3.319.18034.dll. Then, I did the same thing with SOS.dll.

Then when this didn't work, I found a stack overflow post suggesting the 32 bit Task Manager solution.

Thursday, August 28, 2014

I keep losing bits of code that do this. I like to make my brain work while it reads. I get bored with the act of reading quickly sometimes. This puts a complete halt to the boredom/lack of challenge.


$filename = "C:\Users\Ogre\Documents\Calibre Library\Catch-22\Joseph Heller (30)\Joseph Heller - Catch-22.txt"
$text = [System.IO.File]::ReadAllText($filename);
$output = ""
for($i = 0; $i -lt $text.Length; $i++){
 $currentAsciiValue = [int]$text[$i];
 
 if($currentAsciiValue -gt 64 -and $currentAsciiValue -lt 91) {
  $output += [char]($currentAsciiValue + 1)
 } elseif($currentAsciiValue -gt 96 -and $currentAsciiValue -lt 123) {
  $output += [char]($currentAsciiValue + 1)
 } else {
  $output += [char]($currentAsciiValue)
 }
}
$output >> Catch22Ciphered.txt

Saturday, May 17, 2014

Sketchup Plugin #1


Here's the ruby that I wrote for a plugin for Sketchup.


require 'sketchup' def do_curve(x) a1 = 0 a2 = 0 a3 = 4.7173806e-006 a4 = -1.13578e-007 a5 = 8.4145793e-010 r = -1.111234 c = 1.0/r k = -3.739907 return (c * x * x) / (1 + (1 - (1 + k) * c * c * x * x) ** 0.5) end def draw_curve model = Sketchup.active_model entities = model.entities model.start_operation "DrawCurve" last_num = 0 last_y = 0 for i in -1000 .. 1000 floati = i.to_f / 100 y = do_curve(floati) if i != -1000 Sketchup.active_model.entities.add_line [floati, y, 0], [last_num, last_y, 0] end last_num = floati last_y = y end model.commit_operation end UI.menu("PlugIns").add_item("Draw Curve") { draw_curve } #draw_curve
I used this to draw a curve in sketchup, which I turned into a 3d shape to print out on my 3d printer.

This represents some interesting skills that I've acquired.
1) The ability to program in Ruby, or rather the skill to write a short program in an unknown language in about an hour.
2) The ability to programmatically control a 3d modelling program, in this case sketchup.
3) The ability to turn that 3d model into a physical object, using a 3d printer.


Tuesday, March 25, 2014

Dilbert Me in F#

This is the Dilbert download tool in F#, just because I like playing with F# and making up reasons to do so.

I switched to WebClient here instead of WebRequest. It makes things a little easier and I clearly should have been using it all along.

I wrote it in Visual Studio 2013 as a F# script file. I selected all then hit 'alt+enter' to run it.

FsLight was what I was led to when googling F# code formatters. It was easy to use and seems to have done a good job.

1
2
3
4
5
6
7
8
let webClient = new System.Net.WebClient()
let url = "http://www.dilbert.com"
let dilbert = webClient.DownloadString(url)
let innerUrl = "http://www.dilbert.com/" + System.Text.RegularExpressions.Regex.Match(dilbert, "src=.*strip.gif").Value.Substring(5)
innerUrl
let innerTempFile = System.IO.Path.GetTempFileName() + ".gif"
webClient.DownloadFile(innerUrl, innerTempFile)
System.Diagnostics.Process.Start(innerTempFile)
Created with FsLight

Monday, March 17, 2014

Dilbert Me 2

The previous powershell script for dilbert broke. It seems the cartoons aren't sequential. This is try #2. 

$url = "http://www.dilbert.com" 
$httpRequest = [Net.WebRequest]::create($url)

$response = $httpRequest.GetResponse()
$stream = $response.GetResponseStream()
$buffer = @()
$binaryReader = New-Object System.IO.BinaryReader($stream)

$tempBuffer = $binaryReader.ReadBytes(1024)
while($tempBuffer.Length -eq 1024) { 
    $buffer += $tempBuffer
    $tempBuffer = $binaryReader.ReadBytes(1024)
}

$dilbert = [System.Text.ASCIIEncoding]::UTF8.GetString($buffer)

$url = "http://www.dilbert.com/" + [System.Text.RegularExpressions.Regex]::Match($dilbert, "src=.*strip.gif").Value.Substring(5)

$url 

$httpRequest = [Net.WebRequest]::create($url)

$response = $httpRequest.GetResponse()
$stream = $response.GetResponseStream()
$buffer = @()
$binaryReader = New-Object System.IO.BinaryReader($stream)

$tempBuffer = $binaryReader.ReadBytes(1024)
while($tempBuffer.Length -eq 1024) { 
    $buffer += $tempBuffer
    $tempBuffer = $binaryReader.ReadBytes(1024)
}

$buffer += $tempBuffer
$tempFile = [System.IO.Path]::GetTempFileName() + ".gif"
[System.IO.File]::WriteAllBytes($tempFile, $buffer)
.$tempFile

Tuesday, March 11, 2014

Dilbert Me!

My RSS reader (feedly) doesn't handle Dilbert well. Probably because they want me to view all the advertising surrounding the daily Dilbert cartoon. So it opens up an external browser and forwards me to Dilbert.com from the RSS reader. This is annoying. This powershell script opens up today's Dilbert and shows just the strip. I should wrap this in it's own RSS feed... eventually

$startDate = New-Object DateTime(1425, 9, 14)
$days = [DateTime]::Now.Subtract($startDate).Days
$hundredThousands = [Math]::Floor( $days / 100000)
$tenThousands = [Math]::Floor( ($days % 100000)/10000)
$thousands = [Math]::Floor( ($days % 10000)/1000)
$hundreds = [Math]::Floor( ($days %1000) /100)
$remainder = [Math]::Floor( ($days %100))
#http://dilbert.com/dyn/str_strip/000000000/00000000/0000000/200000/10000/4000/900/214940/214940.strip.gif
$url = "http://dilbert.com/dyn/str_strip/000000000/00000000/0000000/" + $hundredThousands + "00000/" + $tenThousands + "0000/" + $thousands + "000/" + $hundreds + "00/" + $days + "/" + $days + ".strip.gif"

$httpRequest = [Net.WebRequest]::create($url)

$response = $httpRequest.GetResponse()
$stream = $response.GetResponseStream()
$buffer = @()
$binaryReader = New-Object System.IO.BinaryReader($stream)

$tempBuffer = $binaryReader.ReadBytes(1024)
while($tempBuffer.Length -eq 1024) { 
 $buffer += $tempBuffer
 $tempBuffer = $binaryReader.ReadBytes(1024)
}

$buffer += $tempBuffer
$tempFile = [System.IO.Path]::GetTempFileName() + ".gif"
[System.IO.File]::WriteAllBytes($tempFile, $buffer)
.$tempFile

Wednesday, March 5, 2014

Drawing in a canvas.

I created an html 5 canvas object.
Mouse down to draw in it.

Sadly, this only works if it is the only post viewed.
JSFiddle was very useful in debugging this and getting it to work. I did the development on a PC, and tested the results immediately in a browser on a tablet and on my phone.



Monday, June 17, 2013

How to write a loop, or lambda expression, in the immediate window, part 2

$dte is the key.

That whole nuget package manager console window, that is a powershell window, that gives you easy access to the visual studio automation model, is neat, very powerful, and, as I have discovered, a treasure trove of Visual Studio arcana.

EnvDTE.DTE is easy to get at when you are in the context of an add-in that you have written yourself. Exposing it in ready made powershell window, is a complex and involved trick. Writing that whole powershell console as an add-in inside of Visual Studio, after reading the source code at nuget.codeplex.com, appears to be an elegant work of coding art.

But.. back to $dte, my favorite powershell-nuget-visualstudio variable. Here is the code that worked the magic and populated the variable inside of powershell:

 
        [System.Diagnostics.CodeAnalysis.SuppressMessage(
           
"Microsoft.Reliability",
           
"CA2000:Dispose objects before losing scope",
            Justification =
"We can't dispose it if we want to return it.")]
       
private static Tuple CreateRunspace(IConsole console, string hostName)
        {
            DTE dte = ServiceLocator.GetInstance();
InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
            initialSessionState.Variables.Add(
               
new SessionStateVariableEntry(
                   
"DTE",
                    (DTE2)dte,
                   
"Visual Studio DTE automation object",
                    ScopedItemOptions.AllScope | ScopedItemOptions.Constant)
            );
// this is used by the functional tests
           
var packageManagerFactory = ServiceLocator.GetInstance();
           
var pmfTuple = Tuple.Create<string, object>("packageManagerFactory", packageManagerFactory);
Tuple<string, object>[] privateData = new Tuple<string, object>[] { pmfTuple };
var host = new NuGetPSHost(hostName, privateData)
            {
                ActiveConsole = console
            };
var runspace = RunspaceFactory.CreateRunspace(host, initialSessionState);
            runspace.ThreadOptions = PSThreadOptions.Default;
            runspace.Open();
//
           
// Set this runspace as DefaultRunspace so I can script DTE events.
           
//
           
// WARNING: MSDN says this is unsafe. The runspace must not be shared across
           
// threads. I need this to be able to use ScriptBlock for DTE events. The
           
// ScriptBlock event handlers execute on DefaultRunspace.
           
//
            Runspace.DefaultRunspace = runspace;
return Tuple.Create(new RunspaceDispatcher(runspace), host);
        }
 
 
 
So here is what I learned from strolling down this rabbit hole.
  1. They brute forced the whole console window. They didn't recycle any sort of existing powershell or command window. They wrote a new one and dealt with all the keypress by keypress nastiness that is involved therein.
  2. $dte is actually spelled $DTE, and just a variable passed into a Runspace through its InitialSessionState.
  3. OpenSource code is fun.

Also, and unrelated to codeplex and nuget, if you want to create a headless $dte object, or rather one connected to a new instance of visual studio 2012, that is simply:

$dte = New-Object -comobject VisualStudio.DTE.11.0

Getting the running obect is done like this:

$dte = [System.Runtime.InteropSrevices.Marshal]::GetActiveObject("VisualStudio.DTE.11.0")

Wednesday, June 12, 2013

How to write a loop, or lambda expression, in the immediate window

First, you can't write lambda expressions in the immediate window. There are some very good, boring reasons why this is the case. Jared Par explains here...

However, what you really wanted to do is write a loop inside the immediate window because there is some particular debugging goal that you are trying to achieve. This post is about how you can do that.

For example, let's say we have an array of a large number of elements, 1000 or so should do. Let's also say that there is one piece of data in that array that is relevant. We wish to inspect each element individually and test the validity of each item. The following code snipped creates this situation.

static void Main(string[] args)
{ 
  List<int> ints = new List<int>();
  for (int i = 0; i < 1000; i++)
  {
    ints.Add(i);
  }
 
 
  Random random = new Random();
  ints[random.Next(1000)] = -12;
  Console.ReadLine();
}

In this artificial case we're looking for the index of the element in the array that is equal to -12.

The immediate window forces us to do this one item in the array at a time. Potentially taking 1000 user-interactive steps.

Since that method sucks, here's an alternative:
  1. Run the program in the debugger and set a breakpoint on the ReadLine() statement.
  2. Open up the nuget package manager console.
  3. Write some clever powershell that does the evaluation and looping for us.
The clever bit of powershell code that is necessary starts with something like this:

$dte.Debugger.GetExpression("expression", 1, $true)

$dte is the variable that contains the Visual Studio automation model.
Documentation about $dte is here.

In our case, the completed powershell expression looks like this:

for($i = 0; $i -lt 1000; $i++) { $a = $dte.Debugger.GetExpression("ints[$i]"); if ($a.Value -ne $i) { Write-Host $a.Value $i } }

Or, broken into multiple, more readable lines:

for($i = 0; $i -lt 1000; $i++) {
  $a = $dte.Debugger.GetExpression("ints[$i]");
  if ($a.Value -ne $i) {
    Write-Host $a.Value $i
  }
}

This rather neatly writes out the index we're looking for and the value found there. 



















The anomalous value (-12) wound up in the 604th element of the array. Groovy.

Most programmers aren't going to do this. It requires good knowledge of powershell, some knowledge of the Visual Studio automation model, and an interesting and difficult debugging problem before it is useful.

But it is fun.