Pokazywanie postów oznaczonych etykietą tool. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą tool. Pokaż wszystkie posty

niedziela, 27 lipca 2014

Count lines of code

CLOC to tool do wyliczenia liczby plików różnych formatów oraz wylicza ile jest tych linijek kodu oraz komentarzy w tych plikach.Jest to tool, bardzo prosty w działaniu. Zacząłem pisać wrapper na PowerShella.
Pierwsza funkcja już jest:
function Get-Loc
{
    param($location="."
)
    $commandLine = "$location --csv"
    $clocResult = & $clocPath $location --csv
    $indexOfLineCsvToParse = [array]::IndexOf($clocResult, "")
    if($indexOfLineCsvToParse -lt 0)
    {
        throw "cant get empty line in cloc result"
    }
    $csvToparse = $clocResult[$indexOfLineCsvToParse..($clocResult.Length)]
    $csvFeed = ConvertFrom-Csv $csvToparse -Delimiter ',' | select  files,language,blank,comment,code  

    return  $csvFeed | %{
        return New-Object PSObject  -prop @{
                                    Files = [int]($_.files);
                                    Language = $_.language;
                                    Blank = [int]($_.blank);
                                    Comment = [int]($_.comment);
                                    Code = [int]($_.code);
                               }
                    } 
}
Aby wyświetlić statystykę projektów to wystarczy wywołać:
 Get-Loc "C:\ProjectDir"
Skrypt jest dostępny w github'a.

sobota, 15 lutego 2014

Skróty klawiszowe do VS

Jak wiadomo skróty klawiszowe są bardzo przydatne bo polepszają naszą produktywność, więc dobrze jest mieć skróty dopasowane do własnych potrzeb. Z indywidualnymi skrótami klawiszowymi jest jeden problem - osoba, która nie zna twoich skrótów może mieć problemy z obsługą środowiska programistycznego, już nie mówiąc o takim dziwnym tworze jak Ping-Pong Pair Programming. Ja mam skróty dopasowane do siebie i osoby na moim komputerze nie wiedzą jak ja mogę w ogóle kodować :)

Poniżej jest tabelka ze skrótami. Wywołanie polecenia składa się z kombinacji skrótów. Pierwszy skrót oznacza grupę, a drugi skrót już konkretne polecenie. Jeżeli chcesz odpalić polecenie debugowania to korzystasz z grupy RUN (CTRL + R) i polecenie Debug.Start (CTRL + D). Jeżeli bez chcesz uruchomić bez debagowania to pod tej samej grupie jest polecenie Debug.StartWithoutDebugging (CTRL + SHIFT + D).
Niektóre skróty już coś oznaczają (CTRL + F czy CTRL + A), więc musiałem dołożyć dodatkowy klawisz.



Plik z ustawieniami importu w Visual Studio jest poniżej:


Moje skróty ewoluują, Wcześniej miałem skrót do zen codingu, czy do GhostDoc'a. Czasami skróty są zależne od projektu.

wtorek, 11 lutego 2014

PowerShell i GraphViz

Już wcześniej pisałem o grafie w Power Shellu, a tym razem o przedstawieniu połączeń w grafie na obrazie. Do przedstawienia grafu użyjemy darmowego narzędzia GraphViz. Użyjemy grafu z poprzedniego wpisu.


$graph  = Create-Graph | 
    Add-Edge -edge (Create-Edge A B  1 ) |
    Add-Edge -edge (Create-Edge A C  5) |
    Add-Edge -edge (Create-Edge A D  3) |
    Add-Edge -edge (Create-Edge A E  11) |
    Add-Edge -edge (Create-Edge B C  9) |
    Add-Edge -edge (Create-Edge B D  1) |
    Add-Edge -edge (Create-Edge B E  2) |
    Add-Edge -edge (Create-Edge C D  6) |
    Add-Edge -edge (Create-Edge C E  4) |
    Add-Edge -edge (Create-Edge D E  3) 



Rozdzielimy to zadanie na 2 części. Pierwsza część będzie translacja grafu do języka dot używanego w GraphVizie (w praktyce jest to zapis danych w podobnej postaci co przykład z galerii GraphViz).
function ConvertTo-GraphViz
{
        param(
        [Parameter(Mandatory=$true, Position=1,ValueFromPipeline=$true)]  
        [ValidateNotNull()]  
        $graph,

        [ValidateNotNullOrEmpty()] 
        [string]$name='G',

        [ValidateRange(8, 52)]
        [int]$fontSize =12,

        [ValidateNotNullOrEmpty()] 
        [string]$label='Graph from PowerShell',
        
        [ValidateNotNullOrEmpty()] 
        [string]$arrowSign = '->',

        [ValidateNotNullOrEmpty()] 
        [ValidateSet('LR','RL')]
        [string]$rankdir='LR'
    )
    begin{
#region Strings
        $templateBegin ="digraph $name {
rankdir=$rankdir;
"
        $templateEnd = "
fontsize=$fontSize;
}"
        $templateBody= ''
        $format = "{0} $arrowSign {1} [label = {2} ];
"
#endregion
        }
    process{
        $graph.Edges | %{ 
             $templateBody += $format -f $_.From, $_.To, $_.Weight
            }

        }
    
    end{
        return $templateBegin + $templateBody + $templateEnd 
    }
}



Drugą częścią zadania będzie zapisanie kodu dot do pliku i uruchomienie aplikacji, która przekonwertuje do obrazu przedstawiającego ten graf:
function Out-GraphViz
{
    param(
    [Parameter(Mandatory=$true, Position=1,ValueFromPipeline=$true)] 
    [ValidateNotNullOrEmpty()] 
    $graphVizDot,
    
    [ValidateNotNullOrEmpty()]
    [string]$fiepath='PsGraphViz.png',
    [ValidateNotNullOrEmpty()]

    [stinrg]$dotFilePath ='PsGraphViz.dot',
    
    [ValidateNotNullOrEmpty()]
    [ValidateSet('bmp', 'canon', 'cmap', 'cmapx', 'cmapx_np', 'dot', 'emf', 'emfplus', 'eps', 'fig', 'gd', 'gd2', 'gif', 'gv', 'imap', 'imap_np', 'ismap', 'jpe', 'jpeg', 'jpg', 'metafile', 'pdf', 'pic', 'plain', 'plain-ext', 'png', '
pov', 'ps', 'ps2', 'svg', 'svgz', 'tif', 'tiff', 'tk', 'vml', 'vmlz', 'vrml', 'wbmp', 'xdot', 'xdot1.2', 'xdot1.4')]
    [string]$format='png'
    )
    process{

        $graphVizDot| Out-File -FilePath $dotFilePath -Encoding ascii 

        $cmdpath  ="~\Programs\graphviz\bin\dot.exe"
        Write-Verbose "Running app from $cmdpath"
        Invoke-Expression "& `"$cmdpath`" -T$format -o $fiepath $dotFilePath" 
    }
}



Wywołanie wygląda następująco:
$graph | ConvertTo-GraphViz  | Out-GraphViz

A po tej komendzie zostaną wygenerowane 2 pliki (dot plik oraz obraz grafu):

niedziela, 19 stycznia 2014

Troszkę więcej niż VS Clean za pomocą PS

Komenda Clean w Visual Studio jest do czyszczenia zawartości ostatnio kompilowanego projektu. Nie oznacza to usunięcie całej zawartości folderów bin lub obj (lub subfolderów Debug/Releas), ale usunięcie tylko execów, dllki itp plików. Jest to problem kiedy chcemy mieć pewność, że wszystko zostało wyczyszczone lub kiedy musimy co jakiś czas archiwizować buildy. Nie wiem czy jest taka opcja w Visual Studio, aby za pomocą jednego polecenia dało się usunąć całą zawartość folderów bin i obj.

Standardowo musiałem ręcznie usuwać zawartość tych katalogów, ale pomyślałem sobie czy nie lepiej jest napisać skrypt w PowerShell, który mógłby tą czynność wykonywać za mnie.
function Remove-CsprojBuildFiles
{
    param(
    [string]$dirPath = "."
    )

    $buildDirName = "bin","obj"
    
    Write-Host "Deleting all `"$buildDirName`" dirs from $dirPath"

    $dirsThatAreContainers = get-childitem  $dirPath -Recurse | 
        ? { $_.PSIsContainer}  

     $dirsThatAreBuildNames =    $dirsThatAreContainers |
        ? {$buildDirName -contains $_.Name  }

        $dirsWhichContainsCsprojFile = $dirsThatAreBuildNames |
        ? { ((gci  -path $_.Parent.FullName) |?{$_.FullName.Contains("csproj") } | Test-Any )}


       $dirRemovedCounter= 0
       foreach($dir in $dirsWhichContainsCsprojFile)
       {
            $dirFullPath  = $dir.FullName
            if(Test-path $dirFullPath )
            {
                Remove-Item -Path $dirFullPath -Recurse
                $dirRemovedCounter+=1
            }
            else 
            {
                Write-Error "Dir $dirFullPath not exists"
            }
       }

    Write-Host "$dirRemovedCounter dirs removed from $dirPath"
}

Przydatna będzie funkcja test-any (taki Any z Linq), którą zapożyczyłem stąd.
function Test-Any() {
    begin {
        $any = $false
    }
    process {
        $any = $true
    }
    end {
        $any
    }
}

Wywołanie polecenie do usuwania katalogów jest następująca:
Remove-CsprojBuildFiles "C:\code\'folder_to_solution'"

niedziela, 10 listopada 2013

Zabawa z blockly

Pamiętasz może Logo Komeniusza - prosty graficzny język programowania powstały na Massachusetts Institute of Technology w USA w latach '70, aby wprowadzić dzieci w świat programowania :) Super idea i gdyby nie ten język, wiele dzisiejszych programistów (w tym ja - tak uczyłem się go w gimnazjum i jestem z tego dumny ) nie robiło by togo, co teraz robi.
Znalazłem projekt blockly, który bardzo przypomina programowanie żółwia.

Oczywiście można zagrać w układnie algorytmu do rozwiązywania labiryntów.



Oprócz tego blockly można programować za pomocą schematów blokowych:





Istnieją też projekty, w których blockly jest wykorzystywany do bardziej trudniejszych problemów.


Myślę, że za kilka (kilkanaście) lat każda osoba będzie w stanie zaprogramować swojego 'robota' za pomocą schematu blokowego.

piątek, 8 listopada 2013

Róźne zwracane wartości w Moq

Moq jest fantastyczne, bardzo przejrzyste, proste w nauczeniu się oraz popularne narzędzie do mockowania obiektów. Przedstawiam Ci prosty extension metod dla Moq. Metoda dzięki której mock zwraca rożne wartości z podanej listy za każdym wywołaniem.
Będziemy mockować interfejs:
    public interface INumerable
    {
        int GetNumber { get; }
    }
Standardowo, aby uzyskać różne wartości przy wywołaniu należało wykonać coś takiego:
var listOfReturnedelements = new List<int> {1, 4, 1, 8};
int number = 0;
var numMock= new Mock<INumerable>();

numMock
   .Setup(x=>x.GetNumber)
   .Returns(() => listOfReturnedelements[number])
    .Callback(() => number++)
;
Musimy zdefiniować dodatkową zmienną określająca index listy oraz wywołać metodę Callback, aby zwiększać ten index.
Za każdym razem jak wywołamy num.GetNumber() to dostajemy inną wartość tablicy. Poniżej przykład użycia:
var num = numMock.Object;
var list = new List<int>();
for (int i = 0; i < 4; i++)
{
    list.Add(num.GetNumber);                
}

Zamiast tego to możesz skorzystać z metody:
public static void ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup, IEnumerable<TResult> results)
    where T : class
{
            setup.Returns(new Queue<TResult>(results).Dequeue);
}
A kod ustawiający obiekt mockujący wygląda następująco:
numMock
.Setup(x=>x.GetNumber)
.ReturnsInOrder(listOfReturnedelements)

Troszkę krótkie wywołanie, ale bardzo mi się podoba użycie kolejki w rozwiązaniu.

niedziela, 27 października 2013

Korniszonek w BDD

Wymagania szczegółowe aplikacji można zapisać w języku Gherkin. Język ten składa się z 5 słów kluczowych (Given, When, Then, And, But).
Poniżej jest przykład użycia tego języka:

Scenario 1: Zwrot zepsutych butów do magazynu w sklepie
GIVEN: klient kupił buty z naszego sklepu
AND: buty przepuszczają wodę w deszczowe dni
BUT: data zakupu nie starsza niż rok
WHEN: klient zwraca buty,
THEN: buty powinny być w magazynie


Scenario 2: Zakup pasty do butów o 50% taniej przy zakupie butów
GIVEN: klient kupił buty
WHEN: klient chce kupić pastę do butów
THEN: cena pasty do butów o 50% taniej


Są to proste przykłady zastosowania języka Gherkin, które przedstawiają różne zachowania aplikacji.
Więcej można poczytać w książce The Cucumber Book: Behaviour-Driven Development for Testers and Developers oraz na stronie jednego z projektów BDD dla języka php.

W tematyce BDD i Gherkin jestem świeżakiem, ale uważam, że warto zainteresować się tym językiem, gdyż nie wymaga umiejętności programistycznych ze strony testera, PM czy BA, aby napisać przypadek użycia. Książkę jeszcze nie przeczytałem, ale w wolnej chwili muszę się zabrać za nią :)

poniedziałek, 21 października 2013

Kolekcja danych testowych

Jakiś czas temu pisałem o TestCase w NUnit. Czasami takie rozwiązanie może zaoszczędzić troszkę czasu. Zauważyłem, że bardzo często testuje metody dla takich samych danych wejściowych. Dla parametru typu string sprawdzam jak metoda zadziała dla null, pustego stringa i stringa z białym znakiem.
public class SimpleTestClass
{
    [TestCase(null)]
    [TestCase("")]
    [TestCase(" ")]
    public void SimpleTestCase(string parametr)
    {
        Assert.IsTrue(string.IsNullOrWhiteSpace(parametr));
    }
}

A gdyby tak trzymać kolekcję przypadków testowych w oddzielnym miejscu? Mamy taką możliwość - możemy użyć TestCaseSource. Niestety wszystkie metody muszą być statyczne.
[TestCaseSource(typeof(StringTestCaseSource), "NullAndWhiteSpaceStrings")]
public void It_should_return_true(string arg1)
{
   Assert.IsTrue(string.IsNullOrWhiteSpace(arg1));
}

Implementacja metody, która zwraca nam potrzebne dane testowe:
public static class StringTestCaseSource
{
public static IEnumerable<TestCaseData> NullAndWhiteSpaceStrings
{
   get
   {
     yield return new TestCaseData(null);
     yield return new TestCaseData("");
     yield return new TestCaseData(" ");
   }
}
}

Inny przypadek użycia - wartości enumów. Chcielibyśmy uruchomić test dla wszystkich przypadków enuma. Możemy podawać nazwy elementów w enumie jak i jego wartości. Dla enuma:
public enum MoneyDirection
{
        Pay,
        Receive,
}

Możemy napisać proste testy:
[TestCaseSource(typeof(EnumTestCaseSource<MoneyDirection>), "Names")]
public void It_should_parse_moneyDirection_string(string nameOfEnums)
{
           var objectEnum = Enum.Parse(typeof (MoneyDirection), nameOfEnums);
           Assert.IsNotNull(objectEnum);
}
 
[TestCaseSource(typeof(EnumTestCaseSource<MoneyDirection>), "Values")]
public void It_should_parse_moneyDirection_type(MoneyDirection valuesOfEnums)
{
           Assert.IsTrue(Enum.IsDefined(typeof(MoneyDirection), valuesOfEnums));
}
A sama implementacja metod jest następująca:
public static IEnumerable<TestCaseData> Names
{
    get
    {
                return Enum.GetNames(typeof(T))
                       .Select(x => new TestCaseData(x));
    }
}
public static IEnumerable<TestCaseData> Values
{
   get
   {
                return Enum.GetValues(typeof(T))
                      .Cast<T>()
                      .ToTestCaseData(); //with extension method
   }
}

Przypuśćmy, że mamy klasę, która zawiera statyczne formaty dat:
public class DateTimeRequiredFormats
{
        public const string Req1 = "yyyyMMdd"; //const is 
        public readonly static string Req2 = "yyyy  MM  dd";
        public static string Req3 = "yyyy MM dd";
        public string Req4 = ""; //not used because not static
        
        
        ////////////
        public string Req5 { get { return "a"; } }
        public string Req6 { get; set; }
 
        public DateTimeRequiredFormats(string req6)
        {
            Req6 = req6;
        }
 
}

Aby sprawdzić działanie statycznych formatów (Req1, Req2, Req3) wystarczyło wywołać:
[TestCaseSource(typeof(FieldTestCaseSource<DateTimeRequiredFormats>), "Static")]
public void It_should_parse_dateTimeFormat(object arg1)
{
   var dateTime = DateTime.ParseExact("20131029", arg1.ToString(), null,
               DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AllowInnerWhite );
   Assert.AreEqual(new DateTime(2013,10,29), dateTime);
}

A metoda, która zwraca te zmienne ma implementację:
public static class FieldTestCaseSource<T>
{
   public static IEnumerable<TestCaseData> Static
   {
      get
      {
         var propertyInfos = typeof(T).GetFields()
                    .Where(x=>x.IsStatic)
                    .Select(x=>x.GetValue(null))
                    ;
         return propertyInfos.ToTestCaseData();
       }
   }
 }

A co z metoda? Tutaj już jest troszkę trudniejsza sytuacja. Oprócz klasy z metodami to potrzebny będzie nam obiekt, który będzie mógł uruchomić metodę. Poniżej klasa z metodami do uruchamiania w teście:
public class InformationGetter
{
   public static int GetSuperNumber()
   {
     return 77;
   }
 
   public static int GetNotSuperNumber()
   {
      return 7;
   }
 
   public string GetCharAt(int indexNumber)
   {
      return _specialString[indexNumber]
.ToString(CultureInfo.InvariantCulture);
   }
   private string _specialString;
 
   public InformationGetter(string specialString)
   {
     _specialString = specialString;
   }
 
   public void ConsoleWrite()
   {
      Console.WriteLine("ConsoleWirte:" + _specialString);
   }
}
Poniżej sam test. Zauważ, że podany tej tutaj typ zwracany przez metodę (int).
[TestCaseSource(typeof(MethodTestCaseSource<InformationGetter,int>), "Static")]
public void It_should_return_int_bigger_than_0(MethodInvoker<int> staticMethodToInvoke)
{
   Assert.Greater(staticMethodToInvoke.Invoke(), 1);
}
public static class MethodTestCaseSource<T, TReturn>
{
   public static IEnumerable<TestCaseData> Static
   {
     get
     {
       var methodInfos=  MethodTestCaseSource<T>.GetStaticMethods()
                    .Where(x => x.ReturnType == typeof (TReturn));
       var methodInvokers = MethodInvoker<TReturn>.ToInvoker(methodInfos);
       return methodInvokers
                    .ToTestCaseData(x=>x.Method.Name);
      }
   }
   public static IEnumerable<TestCaseData> NonStatic
   {
      get
      {
        var methods = MethodTestCaseSource<T>.GetInstanceMethods()
                    .Where(x => x.ReturnType == typeof(T));
 
        var methodInvokers = MethodInvoker.ToInvoker(methods);
        return methodInvokers
                    .ToTestCaseData(x => x.Method.Name);
       }
   }
}
Klasa MethodInvoker wywołuje daną metodę. Klasa ma dwie postacie (bez i z użyciem generyków). Jedna i druga metoda ma podobną implementację.
public class MethodInvoker<TReturn> : MethodInvoker
{
   public MethodInvoker(MethodInfo methodInfo):base(methodInfo){}
 
   public TReturn Invoke(object obj=null, object[] parameters=null)
   {
     return (TReturn)Method.Invoke(obj, parameters);
   }
 
   public static IEnumerable<MethodInvoker<TReturn>> ToInvoker(IEnumerable<MethodInfo> methodInfos)
   {
     return methodInfos.Select(x => new MethodInvoker<TReturn>(x));
   }
}
Dzięki MethodInvoker możemy też przesyłać metody, które nie są statyczne. Wystarczy dla metody Invoke podać obiekt:
[TestCaseSource(typeof(MethodTestCaseSource<InformationGetter, string>), "NonStatic")]
public void It_should_return_first_char(MethodInvoker<string> nonStaticMethodToInvoke)
{
  InformationGetter getter=new InformationGetter("Abc");
  var fistCharString = nonStaticMethodToInvoke.Invoke(getter, new object[] {0});
  StringAssert.AreEqualIgnoringCase("a", fistCharString);
}

Kod źródłowy projektu jest udostępniony na GitHubie. Coś może dodam do tych kolekcji testcesów np. wygenerowane losowe stringi, dane z plików resx, najważniejsze daty w DateTime, adresy url i mail.
Możesz też zainstalować sobie paczkę nugetową. Wystarczy wpisać:
>Install-Package Nunit.Framework.TestCaseStorage



piątek, 15 marca 2013

PowerShell w matematyce

PowerShell jest fantastycznym narzędziem do poprawienia swojej produktywności. Może przydać się w prostych zadaniach matematycznych.


Między innymi możesz w szybki sposób sprawdzić co zwraca dane wyrażenie matematyczne:
PS>19 * 17 / 13 + 11 - 7
28.8461538461538
Ale należy uważać, gdyż PS nie kieruje się matematyczną kolejnością wykonywana działań, dlatego poniżysz wynik jest inny niż spodziewany:
PS>2 + 2 * 2
6
PowerShell sprawdza jaka operacja jest na pierwszym miejscu oraz jaki jest typ pierwszej zmiennej. Wywołując wyrażenie 1+"2" mamy inny wynik niż wywołując "1"+2.
PS>1+ "2"
3

PS>"1" + 2 
"12"
Śmieszną możliwością PS jest sposób mnożenia stringa:)
PS>"z" * 5 + "...."
zzzzz....
Jak będziesz potrzebował przeliterować od 1 do 10 to wystarczy zapisać 1..10 (poniżej przykład)
PS>write-host (1..10) -NoNewLine -separator " _ "
1 _ 2 _ 3 _ 4 _ 5 _ 6 _ 7 _ 8 _ 9 _ 10
Taki zapis jest znany z innych języków. Pierwszy raz zobaczyłem taki sposób inicjalizacji w Matlabie. Dodawanie zakresów jest też bardzo intuicyjne. Aby przeiterować od -5 do 5 bez zera to wystarczy zapisać:
PS>write-host ( -5..-1 + 1..5 ) -NoNewLine -separator " _ "
-5 _ -4 _ -3 _ -2 _ -1 _ 1 _ 2 _ 3 _ 4 _ 5
Do tego masz możliwości użycia klasy [math], która posiada najważniejsze funkcje matematyczne:
PS> [math] | Get-Member -Static 
I tak możemy w szybki sposób obliczyć procent składany
PS> $initialInvestment * [math]::pow(1+$interestRate, $times) 
PS> 1000 * [math]::pow(1+0.05, 2)
1102,5
Natomiast, aby obliczyć na jaki procent w skali roku zwróciła się inwestycja wystarczy napisać:
PS>[math]::pow($value/$initialInvestment,1/$times) - 1
PS>[math]::pow(1102/1000,1/2) - 1
0,0497618777608568
Co jest bardzo ciekawe w PS to możliwość operacji na jednostkach pamięci.
PS> 1MB
1048576

PS> 9MB
9437184

PS> 1TB
1099511627776
Możesz przedstawić wielkość jednostki pamięci w innej jednostce, na przykład w postaci megabajtów:
PS>1TB / 1MB
1048576
Czasami taki zapis pomaga przy obliczaniu zajmowanej przestrzeni na dysku.
PS>"{0:n3}"-f ((gwmi win32_logicaldisk -Filter "DeviceID='C:'").freespace/1GB)
Uważam, że PowerShell jest narzędziem matematycznym do bardzo prostych zadań. PS nigdy nie będzie (nigdy nie mów NIGDY) narzędziem dla matematyków, ale w pracy administratora fantastycznie się sprawdza jako proste narzędzie matematyczne.

środa, 13 marca 2013

Wizualizacja społeczeństwa na świecie

Miałem przyjemność zapoznania się z narzędziem, które wizualizuje dane statystyczne. To narzędzie nazywa się GapMinder. Za pomocą tego narzędzia można ciekawe rzeczy wywnioskować np. ilość urodzonych dzieci na jedną matkę jest odwrotnie proporcjonalne do PKB, albo wraz ze wzrostem długości życia wzrasta PKB. Za pomocą tego narzędziu można znaleźć pewną korelację rządzącą światem np. PBK i przeżywalność urodzonych dzieci.



Bardzo zachęcam do pobawienia się narzędziem. Poniżej zamieszczam filmiki pokazujące co można z GapMinderem zrobić.












Zastanawiam się czy można zastosować ten tool w nauczaniu dzieci w polskich szkołach. Jak ja chodziłem do szkoły to nie miałem takich możliwości wizualizacji danych. Gdybym jednak miał taką możliwość, to do tej pory bym został statystykoholikiem :)





Możesz pobrac wersje desktopową GapMindera pod tym adresem


środa, 6 marca 2013

Zmiana rozmiaru zdjęć za pomocą PowerShell

Czy masz może bardzo dużo zdjęć w jednym katalogu, musisz zmienić rozmiar tych zdjęć i za każdym razem uruchamiasz program graficzny, aby zmienić rozmiar zdjęcia??
Ja akurat tak miałem wiele razy :)
Jeśli coś powtarzasz wielokrotnie to postaraj się zautomatyzować tą czynność. Poniżej jest skrypt, który zmienia rozmiar zdjęcia.
function Resize-Image {
[CmdletBinding()]
Param(
     [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
     [System.io.FileInfo] $filepath,
     [int] $width=100,
     [int] $height=100,
     [string]$prefix="rs_"
)

PROCESS{
        $filePathFullName = $filepath.FullName
        if( Test-Path $filePathFullName)
        {
            $destName = $prefix+$filepath.name
            $destPath = Join-Path -path  $filepath.DirectoryName $destName
            
            import-bitmap $filePathFullName | resize-bitmap -Width $width -Height $height | export-bitmap  -Path $destPath 
            Write-Host "Resizing into $destPath"
                   
        }
        else {
            Write-Host "Path not found."
            }
        }
}
Przykład użycia jest przedstawiony poniżej:
gci -filter *.bmp |  Resize-Image 

Ten skrypt może u ciebie nie działać, bo prawdopodobnie nie masz PowerShell Community Extensions. Skrypt korzysta z poleceń import-bitmap,resize-bitmap i export-bitmap, które znajdują się w PSCX. Aby zainstalować PSCX, to wystarczy pobrać paczkę ze strony internetowej. Rozpakować do jednej z lokalizacji zawartej w zmiennej $Env:PSModulePath. A na końcu wywołać poniższy skrypt:
Import-Module Pscx -arg ~\PSCX\Pscx.UserPreferences.ps1
Get-Module

Mam nadzieję, że skrypt się przyda :)

piątek, 14 grudnia 2012

Dobre filmy

Czy kiedykolwiek zdarzyło ci się, że oglądałeś film w kinie, na który polecił ci kolega lub trailer był fajny i po parunastu minutach (nie liczę czasu z reklamami przed filmem) okazało się, że jest to kompletny badziew. Ja wtedy siedzę spokojnie i mówię do sobie, że „już zapłaciłem i poświeciłem czas na dojazd do kino, to jeszcze tą godzinę wytrzymam”. Jeżeli miałeś taką sytuacje jak ja, to może ci pomóc mechanizmu zaimplementowany na portalu filmweb. Teraz oglądam te dobre filmy, wygenerowane z rekomendacji.



Ale jakie są dobre, a jakie słabe filmy? Każda osoba ma swój własny gust filmów. Mechanizmem do wyliczania scoringu filmu nazywa się Gustomierz. Korzysta z wielu zmiennych, takich jak gatunek, głosy innych użytkowników czy twórcy filmu. Model do wyliczenia najlepszych filmów działa na bazie algorytmu K-najbliższych sąsiadów.
I pamiętaj. Szanuj swój czas jaki poświęcasz na oglądanie filmów.

czwartek, 13 grudnia 2012

Achievements w Visual Studio

Gry, aby były bardziej atrakcyjniejsze dla gracza, wprowadziło się termin achievementy, czyli osiągnięcia. Za każdą wykonaną specjalną rzecz, odblokowuje się pewne osiągnięcie. Później taki gracz może pochwalić się takim osiągnięciem przed kolegami czy na Facebooku. Osiągnięcia mają już minecraft, WoW czy Team Fortress (razem ze statystyką osiągnięć ). Możesz też zdobywać osiągnięcia na XBox360. Mimo tego, że kilka lat temu każdy potępiał ten pomysł, dziś dla większości graczy stanowią nieodłączną część zabawy. Do tego stopnia, że niektórzy z nich katują godzinami tytuły, na które nigdy by nawet nie spojrzeli, a wszystko po to, aby być na wyższym poziomie w rankingu.

Takie osiągnięcia są też dla Visual Studio. Powstał specjalny plugin do VS. Tak jak w grach komputerowych, za wykonaną czynność dostajemy osiągnięcie. VS Achievements nie tylko bawi, ale również uczy. Wykonując pewne osiągnięcia, możesz się nauczyć pewnych narzędzi, technologii czy sposobów pisania kodu. Jest tez ranking użytkowników VS.



Achievementy w grach wprowadzono po to, aby w prosty sposób mogły wydłużyć spędzanie czasu wolnego przed grą i zwiększyły więzi między graczem a grą. To samo dzieje się z VS. Dodatek do VS2012 można pobrać tutaj.

Nie mam wielkich osiągnięć, ale raz na jakiś czas będę się starał, aby wykonać jakieś 'głupie' osiągnięcie. Poniżej jest moja statystyka.

piątek, 7 grudnia 2012

Rozpakowanie gz w PowerShell

Ostatnio miałem problem z rozpakowaniem dużej ilości spakowanych plików, wiec musiałem napisać skrypt, który będzie mógł rozpakować wszystkie pliki do wyznaczonego katalogu. Z pomocą przyszedł mi Power Shell, a skrypt wyglądał następująco:
$files = gci -Filter *.zip 
$dirInto = (Get-Location).Path
foreach ($file in $files) {
Write-Host "Processing $file"
$shell_app=new-object -com shell.application
$fileFullName = $file.FullName

$zip_file = $shell_app.NameSpace($fileFullName)
$destinationFolder = $shell_app.NameSpace($dirInto) 
$destinationFolder.CopyHere($zip_file.Items())
}
Rozwiązanie znalazłem na blogu msdn.
Wszystko ok, ale jak chciałem rozpakować pliki gz to już miałem problem. Zabrałem się za przerobienie kodu. Nie chciałem, aby rozwiązanie było uzależnione od jakieś aplikacji, na przykład od PowerShell Community Extensions
Na samym początku napisałem kod w c#, który posłużył mi za podkładke,w którym to korzystam z GZipStream.
using (FileStream fsRead =
 new FileStream(filePath, 
               FileMode.Open, 
               FileAccess.Read,
               FileShare.Read))
            {
                string fileName = 
Path.GetFileNameWithoutExtension(filePath);

                using (FileStream outFile = File.Create(Path.Combine(dirname,fileName)))

                using (GZipStream zipStream= 
new GZipStream(fsRead, 
CompressionMode.Decompress))

                    zipStream.CopyTo(outFile); //.NET 4.0
            }

Później zacząłem przerabiać ten kod na skrypt w PS.
function Unzip-Gzip
{
    param
    (
        [String]$inFile,
        [String]$outDir
    )
 
    if (! (Test-Path $inFile))
    {
        "Input file $inFile does not exist."
        exit 1
    }
 
    if (! (Test-Path $outDir))
    {
        "Output direcotri $outDir does not exist."
        exit 1
    }
   

    $inputFile = New-Object System.IO.FileStream $inFile, 
([IO.FileMode]::Open), 
([IO.FileAccess]::Read), 
([IO.FileShare]::Read)


     try{
        $newFileName = 
[System.IO.Path]::GetFileNameWithoutExtension($inFile)

        $newFilePath = 
[System.IO.Path]::Combine($outDir, $newFileName)  

        $outputDir = 
[System.IO.File]::Create($newFilePath)

        try{
            $inputFileGzip = 
New-Object System.IO.Compression.GZipStream $inputFile, ([System.IO.Compression.CompressionMode]::Decompress)

            try{
                $inputFileGzip.CopyTo($outputDir)
            }finally{
                $inputFileGzip.Close()
            }
        }finally{
            $outputDir.Close()
        }
    }finally{
        $inputFile.Close()
    }
}
Niestety nie mogłem wywołać metody CopyTo, gdyż ta metoda pojawiła się dopiero w .NET 4.0 i nie występuje w PS 2.0. Zamiast tej metody stworzyłem funkcje, która mogła przekopiować Stream.
function Copy-Stream 
{
    param
    (
        [System.IO.Stream]$inputStream,
        [System.IO.Stream]$outputStream
    )

 $bufferSize = 1024
 $buffer = New-Object byte[] $bufferSize
 
 while($true)
 {
    $byteCount = $inputStream.Read($buffer, 0, $bufferSize) 
    if ($byteCount -le 0)
    {
        break;
    }
    $outputStream.Write($buffer,0, $byteCount)
 } 
}

Ostatecznie funkcja Unzip-Gzip wyglada tak:
function Unzip-Gzip
{
    param
    (
        [String]$inFile,
        [String]$outDir
    )
 
    if (! (Test-Path $inFile))
    {
        "Input file $inFile does not exist."
        exit 1
    }
 
    if (! (Test-Path $outDir))
    {
        "Output direcotri $outDir does not exist."
        exit 1
    }
   


    $inputFile = New-Object System.IO.FileStream $inFile,
 ([IO.FileMode]::Open), 
([IO.FileAccess]::Read), 
([IO.FileShare]::Read)

     try{
        $newFileName =
[System.IO.Path]::GetFileNameWithoutExtension($inFile)

        $newFilePath = 
[System.IO.Path]::Combine($outDir, $newFileName) 
 
        $outputDir = 
[System.IO.File]::Create($newFilePath)
        try{
            $inputFileGzip = 
New-Object System.IO.Compression.GZipStream $inputFile, ([System.IO.Compression.CompressionMode]::Decompress)

            try{
#$inputFileGzip.CopyTo($outputDir)
#Not in POWERSHELL 2.0
                Copy-Stream  $inputFileGzip $outputDir
            }finally{
                $inputFileGzip.Close()
            }
        }finally{
            $outputDir.Close()
        }
    }finally{
        $inputFile.Close()
    }
}
A skrypt do rozpakowania plików gz wygląda następująco:
$files = gci -Filter *.zip 
$dirInto = (Get-Location).Path
foreach ($file in $files) {
Write-Host "Processing $file"
$shell_app=new-object -com shell.application
$fileFullName = $file.FullName

Unzip-Gzip $fileFullName  $dirInto
}


środa, 23 maja 2012

Starter.bat

Każdego dni rozpoczynam pracę od uruchamiania tych samych programów, przeglądania tych samych stron, czytania tej samej poczty. Aby zautomatyzować proces klikania po wszystkich ikonkach i wpisywania tych samych nazw, stworzyłem mały .bat plik



Poniżej przedstawiam skrypt w pliku Starter.bat:
:: uruchamia pocztę outlook i zaznacza kalendarz
start outlook.exe /select outlook:calendar

:: wchodzi na strony za pomocą domyślnej przeglądarki
start http://arekonsoftware.blogspot.com  
start https://mail.google.com/mail/#inbox 

:: startuje aplikacje (devenv to visual studio)
start devenv  "C:\Users\I\Documents\Visual Studio 11\Projects\MyBigSolution.sln" /projectconfig Debug 

:: otwiera plik
start /D "C:\Users\I\Documents\" ToDo.xls  

Skrypt zawiera przykładowe programy do uruchomienia. Największą zaletą takiego skryptu jest prostota. Za pomocą polecenia start uruchamiamy daną aplikację. Wiem, że ta technika nie jest czymś odkrywczym, ale dla mnie taki mały pliczek pozwala mi na zautomatyzowanie powtarzalnych czynności. Ta technika jest przydatna, jeżeli masz więcej niż 5 aplikacji do uruchomienia.


piątek, 9 marca 2012

Flock się skończył

Projekt Flock był genialną przeglądarką internetową na silniku chromium dedykowany dla osób prowadzących blog lub korzystających z serwisów społecznościowych takich jak: MySpace, Facebook, YouTube, Twitter, Flickr, Blogger, Gmail, Yahoo! oraz WordPress.
W styczniu 2011 roku Flock Inc. został kupiony przez Zynga, a wsparcie dla Flock zakończyło się 25 kwietnia 2011. Portal Flock.com przestał istnieć. Twórcy zalecają przeniesienie się na Chrome lub Firefox. Starą wersję (2.6.1) można jeszcze pobrać z tego linka.

środa, 7 marca 2012

Zombie Font

Natrafiłem na bardzo śmieszną, a zarazem przerażającą czcionkę na portalu zombiefont.com, na którym można wygenerować tekst za pomocą zombies. Wygenerowałem moje imię i nazwisko i pomyślałem sobie, żeby wygenerować ewolucje mojego podpisu.



Poniżej przedstawiam cały alfabet (niestety bez polskich znaków).




Podobne możliwości udziela portal e-zombie.com, który również może generować połamane zombies.