[{"content":"AI Architecture in Practice — ArcKit at the Perth AI User Group Last night I had the pleasure of presenting to the Perth AI User Group on a topic I\u0026rsquo;ve spent much of the past year living inside: how to get the speed of AI-assisted architecture work without giving up the rigour, traceability and audit trail that enterprise governance demands.\nThe talk — AI Architecture in Practice — centred on ArcKit, the open-source enterprise architecture governance harness created by Mark Craddock (tractorjuice), and how I\u0026rsquo;ve used it end-to-end on real client engagements here in Australia.\nThe problem: \u0026ldquo;can AI draft it?\u0026rdquo; is the wrong question Every architect in the room recognised the starting point:\nScattered documents, no single source of truth. Requirements, risks, decisions and designs live across SharePoint, Confluence, email and slide decks — and drift apart. Weeks of expert effort per artefact. Business cases, risk registers and reviews queue behind delivery; the expert-drafting layer is what everyone waits for. No answer when the auditor asks \u0026ldquo;why?\u0026rdquo; Nothing links a decision back to a requirement, a risk, or a business driver. The audit trail gets reconstructed from memory. Raw GenAI makes it worse, not better. Fast, plausible drafts with no provenance, no gates and no audit trail. Speed without control is a new liability, not a productivity gain. The framing I kept returning to all night: the question is not \u0026ldquo;can AI draft it?\u0026rdquo; — it is \u0026ldquo;can I defend it?\u0026rdquo;\nWhat ArcKit is ArcKit turns AI coding assistants into governed architecture engines. Instead of Word documents and stale Visio diagrams, every artefact — principles, business cases, requirements, risks, decision records, design reviews — is generated by slash commands, written as version-controlled Markdown, and stamped with provenance and traceability.\nFour things make it different from just prompting a chatbot:\nOpen source. MIT-licensed, with docs, playbooks and 40+ public example projects at arckit.org. It runs inside your AI assistant. A plugin for Claude Code (the premier experience), plus Codex CLI, Gemini CLI, GitHub Copilot and OpenCode. Slash commands, not a SaaS platform. Markdown + Git, not documents. Artefacts live in the repo alongside code — versioned, diffable, reviewable via pull request. Governance as code. Governed, not just generated. A harness intercepts every write: gates block unsafe changes, observers stamp provenance, and traceability links artefacts end-to-end. The AI never writes directly to the workspace. That last point is why it\u0026rsquo;s called a harness. Every tool call is intercepted, checked, enriched and stamped — so speed never comes at the cost of control.\nThe Australian overlays Because most of my work sits in Australian regulated sectors, I maintain the arckit-au overlay — community-contributed commands anchored on federal frameworks. Compliance becomes a slash command you run in week one, not a finding you receive in the final month:\nCommand What it produces /arckit:au-pia Privacy Impact Assessment — Privacy Act 1988, APP-by-APP analysis /arckit:au-e8-posture ASD Essential Eight maturity posture (ML0–ML3) /arckit:au-ism-controls ISM Statement of Applicability across 17 control domains /arckit:au-ndb-playbook OAIC Notifiable Data Breaches response playbook /arckit:au-ai-assurance DTA AI Assurance Framework baseline; ISO 42001 readiness /arckit:au-pspf Protective Security Policy Framework scorecard Plus sector packs for critical infrastructure (SOCI/CIRMP), OT security and energy (AESCSF). Install everything with:\nclaude plugin install arckit arckit-au The live demo A worked example of an architecture engagement, governed end to end by ArcKit rather than hand-written.\nThe whole demo workspace is public. Clone it and follow along:\n👉 github.com/SmartTechVentures-au/arckit-demo\nTwo real engagements, same harness The heart of the talk was two anonymised client examples showing ArcKit under genuinely different conditions.\nClient Example 1 — community services provider (NDIS \u0026amp; aged care). Four concurrent mission-critical platform procurements under hard regulatory deadlines. The programme produced 96 governed artefacts across 5 project spaces, including 38 architecture decision records and 27 structured vendor profiles. A 000-global space held org-wide principles, business case and risks; each procurement ran as a numbered project inheriting from it. Structured vendor profiles plus requirements traceability gave the evaluation an auditable evidence base — decisions defensible to the board and to regulators.\nClient Example 2 — ASX-listed industrial technology company. Governance for a new enterprise data platform, with a very different security posture: every artefact carries a PSPF-style classification marking (UNOFFICIAL → PROTECTED) enforced through profile configuration. Notably, this engagement ran on OpenAI Codex CLI while Example 1 used Claude Code — same artefacts, same governance, different AI harness. Assistant-agnostic in practice, not just in the brochure. The full artefact chain — PLAN → STKE → REQ → RISK → DATA → SOBC → HLD → HLDR → ADRs → AUPIA → TRAC → CONF — landed as 30+ governed, versioned, traceable artefacts.\nWhat held across both engagements Six patterns I\u0026rsquo;d stand behind for anyone starting out:\nThe architect\u0026rsquo;s job changes, not disappears. AI drafts to templates; the architect interrogates, decides and signs off. Judgement, stakeholder context and trade-off thinking become the whole job — formatting effort drops to zero. Start with principles and a global space. Org-wide principles plus a 000-global project made every subsequent initiative faster and more consistent. It\u0026rsquo;s the highest-leverage first week you can spend. Traceability changes conversations. When every requirement links to a driver and every decision to a requirement, procurement disputes and audit questions get resolved from the artefacts — not from memory. Overlays make compliance a starting point. Running the AU privacy, cyber and AI-assurance commands early surfaced obligations while the architecture could still absorb them cheaply. Git-native governance meets teams where they are. Pull-request review brought engineers into governance; publishing to DevOps Wiki, Confluence and GitHub Pages brought governance to executives. AI output still needs qualified owners. Community overlays are accelerators, not opinions of record — security, privacy and legal owners review before reliance. The harness makes that review easy, not optional. Getting started Explore — arckit.org has guides, playbooks and 40+ public example projects across health, AI, cloud and data. Install — claude plugin install arckit arckit-au. Free, open source. Pilot — pick one live initiative, run /arckit:init, follow the navigator, and put the eight essential artefacts in Git within a fortnight. Thanks to the Perth AI User Group for hosting, and to everyone who stayed for the wine, pizza and the long tail of questions afterwards — the discussion on assistant-agnostic governance and the role of the human reviewer was the best part of the night.\nIf you\u0026rsquo;re wrestling with AI governance on a real programme and want to talk it through, you\u0026rsquo;ll find me at mckelt.com, smarttechventures.au or axurcio.com.\nArcKit is MIT-licensed open source by Mark Craddock (tractorjuice) — github.com/tractorjuice/arc-kit. Community AU overlays should be reviewed with qualified security, privacy and legal owners before reliance.\n","permalink":"https://blog.mckelt.com/articles/2026/architecting-with-ai-and-arckit/","summary":"\u003ch1 id=\"ai-architecture-in-practice--arckit-at-the-perth-ai-user-group\"\u003eAI Architecture in Practice — ArcKit at the Perth AI User Group\u003c/h1\u003e\n\u003cp\u003eLast night I had the pleasure of presenting to the Perth AI User Group on a topic I\u0026rsquo;ve spent much of the past year living inside: how to get the speed of AI-assisted architecture work \u003cstrong\u003ewithout\u003c/strong\u003e giving up the rigour, traceability and audit trail that enterprise governance demands.\u003c/p\u003e\n\u003cp\u003eThe talk — \u003cem\u003eAI Architecture in Practice\u003c/em\u003e — centred on \u003ca href=\"https://arckit.org\" target=\"_blank\"\u003eArcKit\u003c/a\u003e, the open-source enterprise architecture governance harness created by Mark Craddock (\u003ca href=\"https://github.com/tractorjuice\" target=\"_blank\"\u003etractorjuice\u003c/a\u003e), and how I\u0026rsquo;ve used it end-to-end on real client engagements here in Australia.\u003c/p\u003e","title":"AI Architecture in Practice — ArcKit at the Perth AI User Group"},{"content":"Customer Identity and Access Management The Challenge A client was using Salesforce Visualforce portals with custom code to authenticate users in Salesforce via username, password, and community licenses.\nTo enable growth and simplify custom development outside Salesforce, the client decided to move to a Customer Identity and Access Management (CIAM) platform.\nCustomer Identity and Access Management (CIAM) is a subset of the larger Identity and Access Management (IAM) concept that focuses on managing and controlling external parties\u0026rsquo; access to a business\u0026rsquo;s applications, web portals, and digital services. CIAM solutions help organizations manage customer identities while providing security and an enhanced user experience.\nWe were engaged to provide CIAM implementation options, a recommended solution, cost estimates, and implementation timelines.\nScope In Scope Area Requirement MUST/SHOULD/COULD Scope User Registration Sign Up MUST Account object: First Name, Middle Name, Last Name, Address, Email, Phone • Flags for ID verification (Frankie One) • Flags for open banking (Basiq) • Income, Employment, Open Banking Accounts, Monthly Expenses, Assets, Household Account (child/parent objects) • User object: Username, Email, Phone • User profile (community) • User license (Salesforce Community Plus) Verify Email Post-registration MUST User receives an email link to verify login. Verify SMS Post-registration MUST User receives a unique SMS token to verify login. User Login TOTP MUST Login via email link or SMS token. Step-Up Authentication Sensitive areas SHOULD Require extra authentication methods in designated areas. Two-Factor Authentication Login MUST Multiple authentication methods required. User Experience Branding MUST Ability to customize branding for login and site packages. Templates SHOULD Emails and SMS should allow customization. Reporting \u0026amp; Analytics User Management MUST Dashboard to view, modify, and delete sessions, metadata, roles, and accounts. Trend Analysis COULD Usage, signup, and login trend analysis. Administration Account Lockout MUST Lock account after 5 failed attempts; notify admin. Uptime Monitor MUST Service health notifications. Data Residency MUST Data must reside in Australia. OAuth 2.0 Flows MUST Authorization code flows with PKCE. Migration Import Users MUST Allow PIN and user migration. Non-Functional Requirements Scaling MUST Handle 100 logins/day, peak 1000; MAU \u0026lt; 50,000. Environments MUST Provide non-production environment for development/testing. API Access Management Role Authorization SHOULD Authorize users and roles to APIs. Development SDK Integration SHOULD Provide client libraries for easy integration. Out of Scope Password-based logins or storing passwords Anything not explicitly in scope Security Considerations The recommended authentication protocol for modern web and mobile authentication is OpenID Connect (OIDC), built on OAuth 2.0 and using JSON Web Tokens (JWTs).\nThe Proof Key for Code Exchange (PKCE) extension strengthens OAuth authorization code flow, replacing insecure implicit flows for SPAs and native apps. These app types are vulnerable to reverse engineering and cannot securely store client secrets, making PKCE essential.\nOIDC with PKCE is the recommended approach for a secure, modern authentication solution.\nSelection Criteria Meets Requirements Must satisfy all in-scope functional and non-functional requirements.\nSecurity \u0026amp; Compliance Must meet Australian consumer data requirements under the Privacy Act 1988 and subsequent amendments.\nPricing Consider total cost of ownership: setup, licensing, maintenance, upgrades.\nDeployment Time Effort required to deploy (SaaS, COTS, or OSS) including configuration, branding, and environments.\nScalability Should scale to ~6,000 MAUs in 2 years, with cost-effective pricing.\nSupport Level of vendor support, including technical assistance, updates, training, and documentation.\nFlexibility Adaptability to future technology, business, and regulatory changes.\nOptions Analysis Do Nothing Overview Continue with custom Salesforce SAML authentication and authorisation Benefits Minimal changes in the immediate term. Existing SAML login already in production. Disadvantages Reliant on Salesforce Community Licenses (limits on free tier). Risks Ongoing custom development and maintenance costs. In-house development may exceed cost of third-party CIAM. Solution Options AWS Cognito aws.amazon.com/cognito\nFully managed service by AWS. Features: user pools, identity pools, federated identities. Negative sentiment around documentation/configuration. Auth0 auth0.com\nIndustry leader (owned by Okta). Strong UX and documentation. Expensive as usage scales. FusionAuth fusionauth.io\nOpen-source, modular IAM platform. SaaS and self-hosted options; AWS Marketplace available. Keycloak keycloak.org\nPopular open-source IAM solution. Requires self-hosting (AWS Marketplace option available). Adopted by CNCF; leading OSS identity option. Kinde kinde.com\nAustralian startup (founded 2022 by Atlassian alumni). Developer-focused, catching up on features. Evaluation of Solution Options AWS Cognito Auth0 FusionAuth Keycloak Kinde Meets Requirements 80% 85% 83% 73% 80% Deployment Cloud Cloud Cloud / Self Self Cloud Pricing Model Pay-as-you-go Pay-as-you-go Freemium / Plans Free / Hosting cost Free tier Free Tier 50k MAUs 7.5k MAUs Unlimited (self), $38 SaaS Unlimited (self) 7.5k MAUs Rec. Monthly Pricing Free $1,085 $400 ~$300 $283 Open Source No No No Yes No Features Core IAM Full IAM, MFA, SSO Full IAM + customization Core IAM Full IAM + feature mgmt Security Strong Strong Strong (open) Strong Strong Scalability High High High High High Ease of Use Easy Easy Easy Complex Easy SLA 99.90% 99.99% 99.95% 99.90% 99.99% Time to Deploy 4–5 weeks 2–3 weeks 2–3 weeks 5–6 weeks 2–3 weeks Maintenance Effort Small Small Medium Large Small Recommended Solution Recommendation: FusionAuth (Starter Plan on Business Hosting via AWS Marketplace) 👉 fusionauth.io/download\nMonthly Cost: $400 Annual Cost: $4,560 Setup \u0026amp; Config Time: 2–3 weeks The Starter Plan includes advanced MFA, password-less and social login, LDAP connectors, SSO, application theming, breached password detection, and more.\nSupport is provided via community channels (forums, Slack, GitHub). Allows up to 10,000 MAUs. Runs on a dedicated EC2 instance with 3-day backups and single-domain support.\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2024/choosing-a-customer-identity-management-system/","summary":"Customer Identity and Access Managment","title":"Choosing a Customer Identity Management System"},{"content":" Mailing address Chris McKelt Blog\nOffice address 191 St. Georges Terrace, Perth, WA 6000 Office location ","permalink":"https://blog.mckelt.com/location/","summary":"\u003chr\u003e\n\u003ch4 id=\"mailing-address\"\u003eMailing address\u003c/h4\u003e\n\u003cp\u003eChris McKelt Blog\u003c/p\u003e\n\u003chr\u003e\n\u003ch4 id=\"office-address\"\u003eOffice address\u003c/h4\u003e\n\u003ch2 id=\"191-st-georges-terrace-perth-wa-6000\"\u003e191 St. Georges Terrace, Perth, WA 6000\u003c/h2\u003e\n\u003ch4 id=\"office-location\"\u003eOffice location\u003c/h4\u003e\n\u003ciframe\r\n  src=\"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d172870.0935786766!2d115.689396087674!3d-31.954473498941404!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x2a32a50f7682e9fb%3A0x304f0b535df4270!2sPerth%20WA!5e0!3m2!1sen!2sau!4v1734521423456!5m2!1sen!2sau\"\r\n  width=\"600\"\r\n  height=\"450\"\r\n  style=\"border:0;\"\r\n  allowfullscreen=\"\"\r\n  loading=\"lazy\"\r\n  referrerpolicy=\"no-referrer-when-downgrade\"\u003e\r\n\u003c/iframe\u003e","title":"Location"},{"content":" Schedule Office hours take place on Monday to Saturday 8am to 6pm (and outside when requested) Location We work remotely by default, but enjoy face to face meetings at your request.\nMeeting Preferences In order of preference - Microsoft Teams, Whereby, Zoom, Slack ","permalink":"https://blog.mckelt.com/officehours/","summary":"\u003chr\u003e\n\u003ch4 id=\"schedule\"\u003eSchedule\u003c/h4\u003e\n\u003ch2 id=\"office-hours-take-place-on-monday-to-saturday-8am-to-6pm-and-outside-when-requested\"\u003eOffice hours take place on Monday to Saturday 8am to 6pm (and outside when requested)\u003c/h2\u003e\n\u003ch4 id=\"location\"\u003eLocation\u003c/h4\u003e\n\u003cp\u003eWe work remotely by default, but enjoy face to face meetings at your request.\u003c/p\u003e\n\u003chr\u003e\n\u003ch4 id=\"meeting-preferences\"\u003eMeeting Preferences\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eIn order of preference - Microsoft Teams, Whereby, Zoom, Slack\u003c/li\u003e\n\u003c/ul\u003e","title":"Office Hours"},{"content":"A guide to integration strategy Which integration method should you use for a given scenario?\nIntegration Decision Tree The integration decision tree is a tool for deciding which integration patterns and technologies should be used to implement an integration. It references approved design patterns, template projects, and standards that should guide implementation.\nThe following decision tree should be used to determine how an integration should be implemented:\nIntegration Types Integrations can be broadly classified as Application Integration or Data Integration:\nApplication Integrations Integrating live operational data in real-time between two or more applications. Example: Calling an API to retrieve information from a 3rd party service, or publishing an event when an application changes state.\nData Integrations Typically batch-oriented, dealing with data at rest (the process that created the data has already completed). Example: Sending invoice or payment data to a finance system on a nightly schedule.\nIntegration Styles Integration style refers to how two systems communicate. For example:\nDoes the calling system get an immediate response? Does the back-end system send notifications? Is information exchanged on a schedule? Real-time Synchronous (Request-Reply) Couples the front-end host to the back-end processing; the front-end must wait for a response before continuing.\nReal-time Asynchronous Decouples back-end processing, but the front-end still needs a response (often via polling). See:\nPolling pattern Async Request-Reply Real-time Asynchronous with Callback (Request-Callback) The back-end calls a URI provided by the front-end once processing completes (success or failure).\nBatch (Unitary) Data exchange on a scheduled basis, decoupled from front-end processing. Often involves background processes generating events/messages.\nBatch (Bulk) Large-scale scheduled data exchange (export/import). Example: Exporting invoices every 12 hours to a file share, then importing them into another system.\nIntegration Styles (Gregor Hohpe, 2003) Gregor Hohpe described four integration styles in Enterprise Integration Patterns (2003):\nAPI (Remote Procedure Call) Direct API integration applies encapsulation, letting each system maintain its own data integrity. Types:\nPrivate APIs Partner APIs SaaS APIs (e.g., GitHub, Stripe) Platform APIs (ERP, CRM, marketplaces) Event or Messaging Transfer of information via messages on a bus.\nEvents: Inform that something happened (lightweight, contextual). Messages: Instruct an action with full details. ETL (Extract, Transform, Load) Scheduled data transfer, transforming source data to fit a target model. Suited for large/bulk transfers or legacy systems.\nNote: Shared databases are excluded as an anti-pattern due to tight coupling.\nIntegration Technologies Approved technologies (DWER context):\nAPI Management Azure API Management APIs are published, secured, monitored, and versioned through APIM. Types:\nProxy APIs – Expose 3rd party services with security/throttling controls. Example: DWER’s ArcGIS API. Microservice APIs – Independently deployable units for bespoke business capabilities. Traits: bounded context, independent deployability, owning their data. See: Microservices Ultimate Guide API Design eBook Service Bus Azure Service Bus A fully managed enterprise message broker with queues and publish/subscribe topics. Supports events and messages, though not event replay at scale.\nPoint-to-Point Direct integrations where reusability is limited. Suitable when out-of-the-box connectors exist or cost/time constraints apply.\niPaaS Azure Integration Services A suite including Azure Functions, Logic Apps, Service Bus, and APIM for enterprise integration.\nETL Tools Off-the-shelf ETL engines with many connectors for extracting, transforming, and loading data.\nUsing the Decision Tree Start If integration is user-initiated → Application Integration If scheduled/triggered → Data Integration Integration Type Application Integration Immediate response → Real-Time Synchronous Deferred response (no callback) → Real-Time Asynchronous Deferred response (callback available) → Real-Time Async with Callback Triggered, per-transaction → Batc Our Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2024/integration-decision-tree/","summary":"A guide to integration strategy","title":"Integration Decision Tree"},{"content":"The Integrations Lifecycle The Integrations Lifecycle follows a Design Thinking – Lean Startup – Agile approach.\nDesign Thinking Design Thinking is an iterative process in which we seek to understand the user, challenge assumptions, and redefine problems to identify alternative strategies and solutions that may not be immediately obvious. It is a solution-focused approach, combining a mindset with hands-on methods.\nIn the context of integration design, requirements are defined by the business processes they support. Design Thinking focuses on understanding business processes, identifying inefficiencies, and ideating integration capabilities that improve those processes.\nIntegration Types Data Integration Batch-oriented, dealing with data at rest (i.e., the process creating the data has already completed).\nApplication \u0026amp; System Integration Real-time integration of live operational data between two or more applications.\nRequest-based (e.g., do this now) Message-based (e.g., do this when you get a chance) Event-based (e.g., this happened) The mode of integration is driven by business process requirements and the constraints of the underlying technology.\nLean Approach The Lean Startup methodology is a scientific approach to problem solving. It draws on feedback data to guide and accelerate iterative integration development.\nThis involves:\nAssessing options against defined criteria Experimenting with technologies and patterns Gaining evidence-based knowledge of performance and constraints Using insights to influence the final design Agile Agile is a way of working, characterized by frequent, incremental delivery of product, and ongoing reassessment and adaptation of plans.\nAPI Strategy APIs are central to integration, service platforms, innovation, and connectivity. They:\nEnable monetization opportunities Enhance core business functions Foster global partnerships and standardization (e.g., Open Banking) When combined with cloud scalability, IoT, and machine learning, APIs provide endless possibilities for innovation. To keep pace, organizations require infrastructure that aligns with business growth, adapts rapidly, and prioritizes usability and monetization.\nOur proven approach to API Strategy helps you:\nAccelerate understanding Bring confidence to investments Fuel agility Avoid complexity and drift API Lifecycle The API Lifecycle follows the CI/CD pipeline for API Management (APIM) approach: 👉 Build a CI/CD Pipeline for API Management\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2024/api-governance/","summary":"The Integrations Lifecycle follows a Design Thinking Lean Startup Agile approach.","title":"API \u0026 Integration Lifecycle Governance"},{"content":"Understand what to measure and how to use them to accelerate your business Focus on metrics that will accelerate your software delivery process, learn how to obtain them and how to improve them\nWhen it comes to measuring an organisation’s ability to develop and operate software systems nothing beats the key metrics identified in the 2019 Accelerate State of DevOps Report by DevOps Research and Assessment (DORA).\nThe report clearly demonstrates the empirical links between high performing software teams and high performing organisations and provides evidence-based guidance on the capabilities and practices that accelerate digital transformation.\nThis research, together with our extensive delivery experience, forms the basis of our DevOps practice.\nThe Solution Discovery workshops and interviews to evaluate the current state, understand measurement potential, and determine metrics\nPresentation report on findings, metric availability and techniques to measure and improve\nBenefits and Outcomes Reference leading research linking software speed, stability and availability to organisational performance\nUnderstand the importance of performance data and identify the key metrics needed\nArticulate their current performance metrics maturity and identify their key gaps and opportunities\nTake immediate action to get the right metrics in place, and build better software, faster!\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2023/measure/","summary":"The Integrations Lifecycle follows a Design Thinking Lean Startup Agile approach.","title":"Measure by Metric"},{"content":"The Pillars of Our Expertise With an extensive track record of working with small to enterprise organisations across diverse industry sectors, Smart Tech specialises in driving large-scale programs of work in cutting-edge areas such as cloud infrastructure, architecture, digital applications, data, and AI.\nOur key strength lies in the invaluable network established by our founders. Having worked extensively with specialists and professionals worldwide, we have cultivated strong relationships and gained exposure to the latest market trends and emerging technologies. This unique advantage enables us to position our specialists precisely where they are needed, when they are needed.\nWhether you require expert guidance in implementing advanced cloud solutions, designing robust architectural frameworks, developing innovative digital applications, harnessing the power of data analytics, or leveraging AI for business growth, Axurcio is your trusted partner. Our deep industry knowledge, combined with our global network, empowers us to deliver exceptional results and drive your organisation’s success.\nExperience the power of Axurcio as we work alongside you to transform your business, unlock new opportunities, and stay ahead in the dynamic and rapidly evolving technological landscape.\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2023/expertise/","summary":"The Integrations Lifecycle follows a Design Thinking Lean Startup Agile approach.","title":"Our Expertise"},{"content":"Microsoft Cloud Adoption Framework For organisations just starting out their journey and those looking to improve their governance structure, we facilitate and deliver the Microsoft Cloud Adoption Framework.\nIf you are starting your cloud journey, there are many aspects to consider when setting up your Azure cloud environment and architecture. Networking, subscription management, security, and governance can all be complex. The Cloud Adoption Framework for Azure provides proven guidance to simplify and streamline this process.\nAxurcio helps organisations adopt the most optimised Cloud Adoption Plan for a smooth transition. We support cloud migration through the phases of Assess, Migrate, Optimize, and Secure \u0026amp; Manage, leveraging cloud-native technologies to modernise solutions.\nOur Approach Delivering successful cloud adoptions by providing a safe environment that fosters innovation with minimal investment and commitment Maintaining a highly trained and certified team skilled in the latest platform innovations Helping you move to the cloud confidently and securely, with audited managed services that free your team to focus on innovation Driving transformation through cloud-native development, building and configuring digital products with modern data stores and flexible networking to solve real business problems Our Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2022/cloud-adoption/","summary":"\u003ch1 id=\"microsoft-cloud-adoption-framework\"\u003eMicrosoft Cloud Adoption Framework\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eFor organisations just starting out their journey and those looking to improve their governance structure, we facilitate and deliver the \u003cstrong\u003eMicrosoft Cloud Adoption Framework\u003c/strong\u003e.\u003c/p\u003e\u003c/blockquote\u003e\n\u003chr\u003e\n\u003cp\u003eIf you are starting your cloud journey, there are many aspects to consider when setting up your Azure cloud environment and architecture.\nNetworking, subscription management, security, and governance can all be complex. The \u003cstrong\u003eCloud Adoption Framework for Azure\u003c/strong\u003e provides proven guidance to simplify and streamline this process.\u003c/p\u003e","title":"Cloud Adoption"},{"content":"Use the DevOps Radar to guide your way Focus on metrics that will accelerate your software delivery process, how to obtain them and how to improve them\nWhen it comes to measuring an organisation’s ability to develop and operate software systems nothing beats the key metrics identified in the 2019 Accelerate State of DevOps Report by DevOps Research and Assessment (DORA).\nThe report clearly demonstrates the empirical links between high performing software teams and high performing organisations and provides evidence-based guidance on the capabilities and practices that accelerate digital transformation.\nThis research, together with our extensive delivery experience, forms the basis of our DevOps practice.\nThe Approach 5 day engagement schedule to suit your team Interviews with technology leaders to evaluate the current state, understand the measurement potential, and determine metrics to measure Data analysis to obtain metrics Radar presentation of insights and detailed action plan for continual improvement Benefits and Outcomes Current state visibility Visual radar Identified issues Actions for improvement Our Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2022/devops-radar/","summary":"\u003ch1 id=\"use-the-devops-radar-to-guide-your-way\"\u003eUse the DevOps Radar to guide your way\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eFocus on metrics that will accelerate your software delivery process, how to obtain them and how to improve them\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003eWhen it comes to measuring an organisation’s ability to develop and operate software systems nothing beats the key metrics identified in the 2019 Accelerate State of DevOps \u003ca href=\"https://services.google.com/fh/files/misc/state-of-devops-2019.pdf\" target=\"_blank\"\u003eReport\u003c/a\u003e by DevOps Research and Assessment (DORA).\u003c/p\u003e\n\u003cp\u003eThe report clearly demonstrates the empirical links between high performing software teams and high performing organisations and provides evidence-based guidance on the capabilities and practices that accelerate digital transformation.\u003c/p\u003e","title":"DevOps Radar"},{"content":" Rationalise your organisation\u0026rsquo;s technology platform and modernise the delivery model, promote standardised, agile and efficient ways of working.\nDefining a Roadmap for Modernisation How can you determine a roadmap for modernisation that enables pragmatic and achievable delivery of digital outcomes and efficiencies?\nWhat type of approach is needed to understand the current state landscape, the business stakeholders involved, and the desired state vision in order to drive business value?\nBusiness Problem vs. Technology Solution We help answer the key questions required to deliver a successful cloud adoption journey:\nIs this the real problem? What do the users need? What technology is right? How do we make it useful? How can we surprise and delight? Our Approach The journey to develop a strategic roadmap for your organisation involves five key phases:\nAlign \u0026amp; Envision Assess Ideate \u0026amp; Design Architect \u0026amp; Roadmap Finalise \u0026amp; Present Engage stakeholders \u0026amp; goals Current application \u0026amp; infrastructure landscape Current state assessment Future-state architecture Strategic objectives Business strategic alignment Current IT imperatives Platform technology envisioning Rehost, Replatform, Rebuild, Replace Summary of findings Our Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2022/digital-estate/","summary":"\u003cblockquote\u003e\n\u003cp\u003eRationalise your organisation\u0026rsquo;s technology platform and modernise the delivery model, promote standardised, agile and efficient ways of working.\u003c/p\u003e\u003c/blockquote\u003e\n\u003ch1 id=\"defining-a-roadmap-for-modernisation\"\u003eDefining a Roadmap for Modernisation\u003c/h1\u003e\n\u003cp\u003eHow can you determine a roadmap for modernisation that enables pragmatic and achievable delivery of digital outcomes and efficiencies?\u003c/p\u003e\n\u003cp\u003eWhat type of approach is needed to understand the current state landscape, the business stakeholders involved, and the desired state vision in order to drive business value?\u003c/p\u003e","title":"Digital Estate Planning"},{"content":"Where possible, we choose to adopt OSS software to avoid vendor lock in. The open source community and specifically the Cloud Native Computing Foundation host a large amount of world class projects, some used under the covers by major cloud providers and charged back to you at a premium. We unlock the value of the global community to power your solutions \u0026amp; endeavour to give back what we can in return.\nWe love OSS Smart Tech is a specialist in open-source software, with deep expertise in Apache Kafka and a wide range of CNCF projects including Dapr, Kubernetes, and OpenTelemetry (OTEL). The company also brings strong capability across modern databases, enabling organisations to build scalable, event-driven, and cloud-native applications. By leveraging these technologies, Smart Tech helps clients design resilient architectures, accelerate innovation, and gain real-time insights from their data while reducing costs and avoiding vendor lock-in.\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2021/oss/","summary":"\u003ch1 id=\"where-possible-we-choose-to-adopt-oss-software-to-avoid-vendor-lock-in\"\u003eWhere possible, we choose to adopt OSS software to avoid vendor lock in.\u003c/h1\u003e\n\u003cp\u003eThe open source community and specifically the \u003ca href=\"https://www.cncf.io/\" target=\"_blank\"\u003eCloud Native Computing Foundation\u003c/a\u003e host a large amount of world class projects, some used under the covers by major cloud providers and charged back to you at a premium. We unlock the value of the global community to power your solutions \u0026amp; endeavour to give back what we can in return.\u003c/p\u003e","title":"OSS"},{"content":"We have deep expertise in Microsoft Azure and help organisations modernise their technology environments by designing and implementing secure, scalable, and cost-effective cloud solutions.\nOur team of certified Azure specialists works across infrastructure, application development, integration, and data services, enabling clients to harness the full potential of the Azure platform.\nAzure Experts We are experts across a range of services across Azure.\nDynamics 365 \u0026amp; Power Platform Dynamics 365 and the Power Platform system and data integration architecture, design, delivery, and support.\nMany organisations already have strong software teams, but they may need a little help. Whether it’s supplementing your existing team or building the foundations of a modern best-practice delivery approach, we help you ship quality software faster.\nOur team of software professionals has decades of industry experience mentoring and supporting other software creators. We provide mentoring by working alongside your team, through to formal training delivered face-to-face or online in real time.\nData \u0026amp; AI Experts We help organisations bring to life their Machine Learning solutions and predictions, making them accessible via web services, Microsoft Azure Machine Learning Studio, and other data-driven channels.\nAzure enables seamless redirection of client application requests to the right services—whether websites hosted inside or outside Azure, mobile applications, or desktop applications such as Excel.\nIoT Experts Azure IoT Edge is a fully managed service built on Azure IoT Hub. It allows you to deploy cloud workloads—such as artificial intelligence and custom business logic—on IoT edge devices using standard containers.\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2021/azure/","summary":"\u003cp\u003eWe have deep expertise in Microsoft Azure and help organisations modernise their technology environments by designing and implementing secure, scalable, and cost-effective cloud solutions.\u003c/p\u003e\n\u003cp\u003eOur team of certified Azure specialists works across infrastructure, application development, integration, and data services, enabling clients to harness the full potential of the Azure platform.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"azure-experts\"\u003eAzure Experts\u003c/h2\u003e\n\u003cp\u003eWe are experts across a range of services across Azure.\u003c/p\u003e\n\u003cimg width=\"1536\" height=\"864\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/aa4c75ea-5a02-4b80-965d-21cfc273916d\" /\u003e\r\n\u003ch1 id=\"dynamics-365--power-platform\"\u003eDynamics 365 \u0026amp; Power Platform\u003c/h1\u003e\n\u003cp\u003eDynamics 365 and the Power Platform system and data integration architecture, design, delivery, and support.\u003c/p\u003e","title":"Azure"},{"content":" FinOps FinOps is a portmanteau of Finance and DevOps, emphasizing communication and collaboration between business and engineering teams.\nAt its core, FinOps is a cultural practice. It enables teams to manage cloud costs by ensuring that everyone takes ownership of their usage, supported by a central best-practices group. Cross-functional teams across Engineering, Finance, and Product work together to accelerate product delivery while maintaining financial control and predictability.\nFinOps Principles FinOps Principles act as the north star for guiding activities within a FinOps practice. They were initially developed by FinOps Foundation members and first introduced in September 2019 as part of the Cloud FinOps book in collaboration with AWS.\nSince then, these principles have expanded to cover multi-cloud environments, evolving as cloud services rapidly change each quarter.\nCloud FinOps Assessment Cloud FinOps-as-a-Service helps organizations reduce cloud spend through continuous engagement.\nThis involves:\nAn initial assessment with actionable recommendations to optimize costs Ongoing consultation with client teams to drive proactive, sustained savings Unlock Cost Reductions for Future Investments We provide detailed insights into:\nCloud utilization Assets and reserved instances Savings plans and ongoing subscriptions These insights uncover innovation opportunities\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2021/finops/","summary":"\u003chr\u003e\n\u003ch1 id=\"finops\"\u003eFinOps\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003eFinOps\u003c/strong\u003e is a portmanteau of \u003cem\u003eFinance\u003c/em\u003e and \u003cem\u003eDevOps\u003c/em\u003e, emphasizing communication and collaboration between business and engineering teams.\u003c/p\u003e\n\u003cp\u003eAt its core, \u003cstrong\u003eFinOps is a cultural practice\u003c/strong\u003e. It enables teams to manage cloud costs by ensuring that everyone takes ownership of their usage, supported by a central best-practices group. Cross-functional teams across Engineering, Finance, and Product work together to accelerate product delivery while maintaining financial control and predictability.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"finops-principles\"\u003eFinOps Principles\u003c/h2\u003e\n\u003cp\u003eFinOps Principles act as the north star for guiding activities within a FinOps practice.\nThey were initially developed by FinOps Foundation members and first introduced in September 2019 as part of the \u003cem\u003eCloud FinOps\u003c/em\u003e book in collaboration with AWS.\u003c/p\u003e","title":"Finops"},{"content":"Series Part 1 - dotnet vs python vs node - temperature emission - who is cooler?\nPart 2 - Developing modules\nPart 3 - Custom Containers using Apache Nifi\nPart 4 - Custom Module using TimescaleDB\nPart 5 - Custom Module using Grafana\nIntro This is part 5 in a series starting here that runs through building an Azure IOT Edge solution. This post will run through setting up Grafana to visualise temperature readings sent from the dot net, python and node custom edge modules.\nThe code is located at: https://github.com/chrismckelt/edgy\nGrafana is the open source analytics and monitoring solution for every database\nSteps to add the module 1. add a new custom module 2. add a new deployment file just for Grafana (and amend the full solution file) 3. create the docker file FROM grafana/grafana:latest # login with admin and below password to web interface ENV GF_SECURITY_ADMIN_PASSWORD [YOUR_GRAFANA_PASSWORD_HERE] ENV GF_AUTH_LDAP_ENABLED=false ENV GF_DATABASE_TYPE postgres ENV GF_DATABASE_HOST timescaledb ENV GF_DATABASE_NAME grafana ENV GF_DATABASE_USER grafana ENV GF_DATABASE_PASSWORD [YOUR_DATABASE_PASSWORD_HERE] COPY ldap.toml /etc/grafana/ COPY custom.ini /etc/grafana/ 4. create the custom.ini make sure to enter the database password on line 75\n5. build and run IoT Edge solution in simulator 6. Navigate to http://localhost:8082/ and login (admin + your grafana password) The Grafana setup board should appear as below\n7. Add data source –\u0026gt; PostgreSQL 8. Add a dashboard query \u0026amp; set the query as below A time series graph will display the 3 temperature readings over time.\nOutro Here we have added Grafana to our IoT Edge solution and created a dashboard from the data stored in TimescaleDB. The generated temperature sent from the 3 modules is analysed by Apache Nifi. When the temperature is greater than 25 degrees a request is sent back to the specific module to activate the air conditioner, which makes the temperature randomly decrease over time.\nThink I would prefer the Python room as it appears the coolest ","permalink":"https://blog.mckelt.com/articles/posts/azure-iot-edge-using-grafana-on-the-edge/","summary":"\u003ch1 id=\"series\"\u003eSeries\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ePart 1 - dotnet vs python vs node - temperature emission - who is cooler?\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-developing-custom-modules-df3\" target=\"_blank\"\u003ePart 2 - Developing modules\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-3rd-party-containers-3mi3\" target=\"_blank\"\u003ePart 3 - Custom Containers using Apache Nifi\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-timescaledb-on-the-edge-2ec1\" target=\"_blank\"\u003ePart 4 - Custom Module using TimescaleDB\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-grafana-on-the-edge-26na\" target=\"_blank\"\u003ePart 5 - Custom Module using Grafana\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"intro\"\u003eIntro\u003c/h1\u003e\n\u003cp\u003eThis is part 5 in a series starting \u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ehere\u003c/a\u003e that runs through building an \u003ca href=\"https://docs.microsoft.com/en-us/azure/iot-edge/about-iot-edge\" target=\"_blank\"\u003eAzure IOT Edge\u003c/a\u003e solution. This post will run through setting up \u003ca href=\"https://grafana.com/\" target=\"_blank\"\u003eGrafana\u003c/a\u003e to visualise temperature readings sent from the dot net, python and node custom edge modules.\u003c/p\u003e","title":"Azure IoT Edge - using Grafana on the Edge"},{"content":"Series Part 1 - dotnet vs python vs node - temperature emission - who is cooler?\nPart 2 - Developing modules\nPart 3 - Custom Containers using Apache Nifi\nPart 4 - Custom Module using TimescaleDB\nPart 5 - Custom Module using Grafana\nIntro This is part 4 in a series starting here that runs through building an Azure IOT Edge solution. This post will run through setting up TimescaleDB to store data published from the dotnet, python and node temperature modules.\nThe code is located at: https://github.com/chrismckelt/edgy\nTimescaleDB: An open-source database built for analysing\ntime-series data with the power and convenience of\nSQL — on premise, at the edge or in the cloud.\nSteps to add the database 1. add the custom module 2. add the section to the deployment file Expose the internal port 5432 that TimescaleDB uses to 8081 for external container use\n3. create the docker file 4. create the database, login and schema 5. run the container and insert data from another module select * from \u0026ldquo;table_001\u0026rdquo; where Isairconditioneron = 0 ORDER BY \u0026ldquo;Timestamp\u0026rdquo; DESC LIMIT 100; Outro Now we have data being saved into the database we can move onto displaying it visually via Grafana in the next post.\n","permalink":"https://blog.mckelt.com/articles/posts/azure-iot-edge-using-timescaledb-on-the-edge/","summary":"\u003ch1 id=\"series\"\u003eSeries\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ePart 1 - dotnet vs python vs node - temperature emission - who is cooler?\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-developing-custom-modules-df3\" target=\"_blank\"\u003ePart 2 - Developing modules\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-3rd-party-containers-3mi3\" target=\"_blank\"\u003ePart 3 - Custom Containers using Apache Nifi\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-timescaledb-on-the-edge-2ec1\" target=\"_blank\"\u003ePart 4 - Custom Module using TimescaleDB\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-grafana-on-the-edge-26na\" target=\"_blank\"\u003ePart 5 - Custom Module using Grafana\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"intro\"\u003eIntro\u003c/h1\u003e\n\u003cp\u003eThis is part 4 in a series starting \u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ehere\u003c/a\u003e that runs through building an \u003ca href=\"https://docs.microsoft.com/en-us/azure/iot-edge/about-iot-edge\" target=\"_blank\"\u003eAzure IOT Edge\u003c/a\u003e solution. This post will run through setting up \u003ca href=\"https://www.timescale.com/\" target=\"_blank\"\u003eTimescaleDB\u003c/a\u003e to store data published from the dotnet, python and node temperature modules.\u003c/p\u003e","title":"Azure IoT Edge – using TimescaleDB on the Edge"},{"content":"Series Part 1 - dotnet vs python vs node - temperature emission - who is cooler?\nPart 2 - Developing modules\nPart 3 - Custom Containers using Apache Nifi\nPart 4 - Custom Module using TimescaleDB\nPart 5 - Custom Module using Grafana\nIntro This is part 3 in a series starting here that runs through building an Azure IOT Edge solution. This post will run through setting up a 3rd party docker container for an edge deployment. The code is located at: https://github.com/chrismckelt/edgy\nIn order to manage data flow \u0026amp; logic on the edge we will deploy a data orchestrator. There are quite a few choices on the market – for this demo we will use Apache Nifi https://nifi.apache.org/.\nApache Nifi describes itself as ‘An easy to use, powerful, and reliable system to process and distribute data.’\nWhat will this module do? The Nifi module will listen to the dot net, python \u0026amp; node module messages and when a temperature exceeds 25°C it will publish a message to activate the air conditioning. The over heating module will receive the message and turn the air conditioning on, thus decrease the temperature.\nThis work was inspired by the following project:\nhttps://github.com/iotblackbelt/nifimodule\nSetting up Nifi To connect Nifi to the edge hub MQTT/AMQP broker (and not using the inbuilt SDKs with code), we need to authenticate with self signed certificates.\nThe easiest way to use self signed certificates for Azure IoT Edge is to follow this tutorial https://docs.microsoft.com/en-us/azure/iot-edge/tutorial-machine-learning-edge-05-configure-edge-device.\nI use the docker image provided in that tutorial to generate my self signed certs. After following the tutorial I upload the ROOT CA to the Azure IoT Hub. After verification it should appear as below:\nWhen working locally with the simulator you will use the generated certs from VS Code. These are found at C:\\ProgramData\\iotedgehubdev\nDeployment files For debugging purposes I made a deployment file that runs only the DotNetGenerator \u0026amp; Nifi. The sections below are also in the full local debug and production template.\nNifi config setup When the Nifi docker file starts it will execute a script to do the following:\ncopy existing files from the local computer using docker bind from c:/config to /config copy the self signed certificates to the Java cert store restart Nifi so the certs and new configuration apply Nifi authentication To connect and publish messages to the MQTT broker we add the following processors in our Nifi flow\nConsumeMQTT PublishMQTT Upon adding a processor you will need to enter the connection details and configure a SSL Context Service to connect to the edge hub broker.\nSSL Context Service setting (certs used are stored in the Java cert store) Settings To generate a SAS token, right click on the device and select ‘Generate SAS Token for Device’ Nifi logic to air con control Using the inbuilt IoT routing system temperature payloads published from dot net, python \u0026amp; node will be pushed to Nifi.\nNifi checks if the temperature recording exceeds 25°C. When this occurs it will publish its own message which is routed back to the overheating module requesting it to turn on the air con.\nIn Nifi this translates to the following processor flows (probably a better way to do this – Nifi experts?)\nNifi flows Running the solution locally Upon starting the solution each module will publish a temperature starting at 20°C . Nifi will receive each message via the Consume MQTT processor. Viewing the data provenance shows all received messages:\nThe modules keep publishing increasing temperatures until Nifi received a temperature over 25°C. Nifi then publishes a message requesting the respective module (e.g. PythonDataGenerator) to decrease the temperature (turn on the air con).\nWatch out when publishing your container to ACR Be careful when publishing your local containers to your remote container registry. I was publishing direct from my machine to my Azure Container Registry. Meanwhile the environment variables were set to look for certificates in the wrong place. So Nifi would not authenticate.\nOutro Here we have shown how to build and deploy a 3rd party container in our edge solution. Once we have the installed the custom certificates Nifi can authenticate to the edge hub and send/receive messages.\n","permalink":"https://blog.mckelt.com/articles/posts/azure-iot-edge-3rd-party-containers/","summary":"\u003ch1 id=\"series\"\u003eSeries\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ePart 1 - dotnet vs python vs node - temperature emission - who is cooler?\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-developing-custom-modules-df3\" target=\"_blank\"\u003ePart 2 - Developing modules\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-3rd-party-containers-3mi3\" target=\"_blank\"\u003ePart 3 - Custom Containers using Apache Nifi\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-timescaledb-on-the-edge-2ec1\" target=\"_blank\"\u003ePart 4 - Custom Module using TimescaleDB\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-grafana-on-the-edge-26na\" target=\"_blank\"\u003ePart 5 - Custom Module using Grafana\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"intro\"\u003eIntro\u003c/h1\u003e\n\u003cp\u003eThis is part 3 in a series starting \u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ehere\u003c/a\u003e that runs through building an \u003ca href=\"https://docs.microsoft.com/en-us/azure/iot-edge/about-iot-edge\" target=\"_blank\"\u003eAzure IOT Edge\u003c/a\u003e solution. This post will run through setting up a 3rd party docker container for an edge deployment. \u003cbr\u003e\nThe code is located at: \u003ca href=\"https://github.com/chrismckelt/edgy\" target=\"_blank\"\u003ehttps://github.com/chrismckelt/edgy\u003c/a\u003e\u003c/p\u003e","title":"Azure IoT Edge – using Apache Nifi as a 3rd party container"},{"content":"Series Part 1 - dotnet vs python vs node - temperature emission - who is cooler?\nPart 2 - Developing modules\nPart 3 - Custom Containers using Apache Nifi\nPart 4 - Custom Module using TimescaleDB\nPart 5 - Custom Module using Grafana\nIntro This is part 2 in a series starting here running through an Azure IoT Edge demo solution located at: https://github.com/chrismckelt/edgy\nThis part will cover developing and running custom modules written in C#, Python and NodeJS.\nIt will focus on commands available in the VS Code interface rather than command line arguments as seen at: https://aka.ms/iotedgedev\nAzure IoT SDKs Azure IoT Edge has a number of SDKs for module development in your favourite language. The SDK code will handle setting up environment variables and provide the boiler plate code necessary to send and receive messages using multiple protocols \u0026amp; channels (e.g. MQTT, AMQP)\nSetting up VS Code to run the local simulator Given the solution is cloned locally and Azure is setup with our IOT Hub we can configure a device to act as a local simulator.\n1. Select IOT Hub \u0026amp; choose your IOT Hub\n2. Create IOT Edge Device - I have named my local device ‘LocalSimulator ‘\n3. Setup IOT Edge Simulator – this will create you edge certs\nThis will generate and install certificates for local development in the following folder \u0026amp; also install the for you note://run VS Code as admin for this\nCreating a module for our solution Right click on the modules folder and select ‘Add IoT Edge Module’.\nThis will then ask a module name \u0026amp; language (C,C#,Java,Node.js, Python)\nI have created numerous custom modules for this solution. For this post we focus on the below 6\nData Generators The demo code shows 3 ‘data generator’ modules written in C#, Python \u0026amp; Node JS.\nEach module publishes a message every second simulating temperature capture. Properties of the sent message are:\nIn C# connecting to the Edge Hub and sending messages can be seen in the following code:\nData Recorders 3 modules in matching languages subscribe to their respective modules published messages\nMessages received are deserialized from JSON format to a POCO and then saved in a database.\nRoutes In order to route messages between modules we use the inbuilt route system in our deployment template file.\nWeb App – Viewer module Finally to view the messages from a web page I have modified an existing demo to that uses SignalR view all messages sent to it from the below routes:\nWhen running the solution you can view all published messages on the web page below\nOutro Here was a basic overview of an demo solution to create and build your own custom IoT Edge modules.\nNext we will introduce an existing docker container (https://nifi.apache.org/)) to act as a data orchestrator. This will subscribe to all \u0026lsquo;Payload\u0026rsquo; messages and publish a message to ‘turn off’ the air conditioner when the temperature is too high.\n","permalink":"https://blog.mckelt.com/articles/posts/azure-iot-edge-developing-custom-modules/","summary":"\u003ch1 id=\"series\"\u003eSeries\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ePart 1 - dotnet vs python vs node - temperature emission - who is cooler?\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-developing-custom-modules-df3\" target=\"_blank\"\u003ePart 2 - Developing modules\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-3rd-party-containers-3mi3\" target=\"_blank\"\u003ePart 3 - Custom Containers using Apache Nifi\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-timescaledb-on-the-edge-2ec1\" target=\"_blank\"\u003ePart 4 - Custom Module using TimescaleDB\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-grafana-on-the-edge-26na\" target=\"_blank\"\u003ePart 5 - Custom Module using Grafana\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"intro\"\u003eIntro\u003c/h1\u003e\n\u003cp\u003eThis is part 2 in a series starting \u003ca href=\"http://blog.mckelt.com/2020/02/13/azure-iot-edge-creating-an-edge-reporting-solution/\" target=\"_blank\"\u003ehere\u003c/a\u003e running through an Azure IoT Edge demo solution located at: \u003ca href=\"https://github.com/chrismckelt/edgy\" target=\"_blank\"\u003ehttps://github.com/chrismckelt/edgy\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThis part will cover developing and running custom modules written in C#, Python and NodeJS.\u003c/p\u003e","title":"Azure IoT Edge - Developing custom modules"},{"content":"Agile Coaching Our coaches focus on embedding Agile at the individual team level, using traditional frameworks like Scrum and Kanban.\nWe may work with one team or multiple teams, including those interacting with groups outside the immediate team. Our focus is on enabling and developing agility at the “make” or “build” level.\nWe ensure that teams can build products the right way and deliver work sustainably.\nWhat We Do Teaching: Scrum, Lean Kanban, SAFe Facilitating: Workshops, kickoffs, retrospectives Consulting: Assessments and recommendations on current processes Mentoring: Scrum Masters, Product Owners, and Engineers to promote best practice Coaching: Using the GROW model — Goal, Reality, Options, Will Our Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2020/agile/","summary":"\u003ch1 id=\"agile-coaching\"\u003eAgile Coaching\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eOur coaches focus on embedding Agile at the individual team level, using traditional frameworks like \u003cstrong\u003eScrum\u003c/strong\u003e and \u003cstrong\u003eKanban\u003c/strong\u003e.\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003eWe may work with one team or multiple teams, including those interacting with groups outside the immediate team. Our focus is on enabling and developing agility at the “make” or “build” level.\u003c/p\u003e\n\u003cp\u003eWe ensure that teams can build products the right way and deliver work sustainably.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"what-we-do\"\u003eWhat We Do\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eTeaching\u003c/strong\u003e: Scrum, Lean Kanban, SAFe\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFacilitating\u003c/strong\u003e: Workshops, kickoffs, retrospectives\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConsulting\u003c/strong\u003e: Assessments and recommendations on current processes\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMentoring\u003c/strong\u003e: Scrum Masters, Product Owners, and Engineers to promote best practice\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCoaching\u003c/strong\u003e: Using the GROW model — Goal, Reality, Options, Will\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"our-technological-competencies\"\u003eOur Technological Competencies\u003c/h1\u003e\n\u003cbr /\u003e\r\n\u003cimg width=\"878\" height=\"497\" alt=\"Smart Tech\" src=\"https://github.com/user-attachments/assets/0863a4fa-501b-46ff-8433-e7ee246ded48\" /\u003e\r\n\u003cbr /\u003e\r\n\u003chr /\u003e\r\n\u003ch3 id=\"could-this-help-you\"\u003eCould this help you?\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"https://smarttechventures.au/contact/\" target=\"_blank\"\u003eContact me for a free discussion\u003c/a\u003e\u003c/p\u003e","title":"Agile"},{"content":"Data Estate Assessment Understand your current state, design your future, analyze the gaps, and make a plan.\nFrom data strategy, building data platforms, data-ops, data governance, advanced analytics, and data science, to creating a data culture — we are the specialist consulting firm that can turn data into real business insights.\nWe bring the people, platforms, tools, and frameworks to unlock the full potential of your data.\nWhat We Deliver We provide a data and analytics assessment along with a future-state roadmap to modernize your digital processes. This helps you leverage your data assets to improve business value and performance.\nOur approach includes:\nAssessing your current data assets Understanding and documenting current processes Prioritizing your data analytics opportunities Building an actionable data management roadmap Our Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2020/data-assessment/","summary":"\u003ch1 id=\"data-estate-assessment\"\u003eData Estate Assessment\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eUnderstand your current state, design your future, analyze the gaps, and make a plan.\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003eFrom data strategy, building data platforms, data-ops, data governance, advanced analytics, and data science, to creating a data culture — we are the specialist consulting firm that can turn data into real business insights.\u003c/p\u003e\n\u003cp\u003eWe bring the people, platforms, tools, and frameworks to unlock the full potential of your data.\u003c/p\u003e\n\u003cimg width=\"1280\" height=\"720\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/809d70d3-9bdf-4661-8d51-a6c15e356bcb\" /\u003e\r\n\u003chr\u003e\n\u003ch2 id=\"what-we-deliver\"\u003eWhat We Deliver\u003c/h2\u003e\n\u003cp\u003eWe provide a \u003cstrong\u003edata and analytics assessment\u003c/strong\u003e along with a \u003cstrong\u003efuture-state roadmap\u003c/strong\u003e to modernize your digital processes. This helps you leverage your data assets to improve business value and performance.\u003c/p\u003e","title":"Data Estate Assessment"},{"content":" DevOps Metrics Workshop Understand what to measure and how to use metrics to accelerate your business. A one-day facilitated workshop focusing on the metrics that will accelerate your software delivery process—what to measure, how to obtain them, and how to improve them.\nWhen it comes to measuring an organisation’s ability to develop and operate software systems, nothing beats the key metrics identified in the 2019 Accelerate State of DevOps Report by DevOps Research and Assessment (DORA).\nThe report demonstrates the empirical links between high-performing software teams and high-performing organisations, providing evidence-based guidance on the capabilities and practices that accelerate digital transformation.\nThis research, combined with our extensive delivery experience, forms the foundation of our DevOps practice.\nThe Solution Discovery workshops and interviews to evaluate the current state, understand measurement potential, and determine metrics Presentation report on findings, metric availability, and techniques to measure and improve Benefits and Outcomes Reference leading research linking software speed, stability, and availability to organisational performance Understand the importance of performance data and identify the key metrics needed Articulate current performance metrics maturity and identify key gaps and opportunities Take immediate action to implement the right metrics and build better software, faster Our Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2020/devops/","summary":"\u003chr\u003e\n\u003ch1 id=\"devops-metrics-workshop\"\u003eDevOps Metrics Workshop\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eUnderstand what to measure and how to use metrics to accelerate your business.\nA one-day facilitated workshop focusing on the metrics that will accelerate your software delivery process—what to measure, how to obtain them, and how to improve them.\u003c/p\u003e\u003c/blockquote\u003e\n\u003chr\u003e\n\u003cp\u003eWhen it comes to measuring an organisation’s ability to develop and operate software systems, nothing beats the key metrics identified in the \u003cstrong\u003e2019 Accelerate State of DevOps \u003ca href=\"https://services.google.com/fh/files/misc/state-of-devops-2019.pdf\" target=\"_blank\"\u003eReport\u003c/a\u003e\u003c/strong\u003e by DevOps Research and Assessment (DORA).\u003c/p\u003e","title":"DevOps"},{"content":"Series Part 1 - dotnet vs python vs node - temperature emission - who is cooler?\nPart 2 - Developing modules\nPart 3 - Custom Containers using Apache Nifi\nPart 4 - Custom Module using TimescaleDB\nPart 5 - Custom Module using Grafana\nIntro This code will run through creating an end to end demo of building \u0026amp; deploying an Azure IoT Edge solution solution.\nCode for this example lives here\nhttps://github.com/chrismckelt/edgy What are we building? This solution demonstrates an air-conditioning monitoring system where 3 room sensors are publishing their temperature over time. When a room gets too hot the air conditioner for that room is turned on. Once the room is cooled it is turned off.\nThree ‘data generator’ modules publish a message with the following properties.\nTimestamp Temperature – room temp in Celsius IsAirConditionerOn – true/false TagKey – room name (in this case dotnet, node, python) Three ‘data recorder’ modules subscribe to the published temperature messages and save the data in a time series database.\nA custom module will listen to all temperature messages and analyse when a room is too hot. Sending a message to turn the rooms air conditioner on.\nDemo Focus Areas show local debug/development options \u0026amp; remote/real deployment how to create and configure an Azure IOT Hub environment in Azure using Azure CLI scripts coding custom modules in .Net, Python, NodeJS (sorry Java) using existing Azure IoT Edge marketplace modules using non-edge marketplace modules (docker images) to save data with Timescale connecting a data flow engine ( Apache Nifi) to the Edge MQTT Broker viewing the data through a Grafana dashboard. Getting started In order to develop solutions for the edge:\nRead Developing custom modules Setup your machine using the Azure IoT EdgeHub Dev Tool I recommend installing these VS code extensions I recommend using Portainer for docker management both locally \u0026amp; on the deployed edge solution Portainer running on http://localhost:9000/ Solution Overview Azure Setup You will need an Azure IoT Hub setup in Azure. For this demo I am using the free tier\nThe IoT Hub Free Edition is intended to encourage proof of concept projects. It enables you to transmit up to a total of 8,000 messages per day, and register up to 500 device identities. The device identity limit is only present for the Free Edition.\nTo build the environment I have used the Azure CLI and created scripts found here. Run the top 3 on your selected subscription to create the artefacts in Azure below:\nRunning\nModules The code contains the docker build files , code \u0026amp; scripts to create the following modules\nCode Descriptions of folders and files Folder / File Description config automatically generate files from the deployment.templates.json (debug or prod) that are used to deploy the solution modules custom code, docker images for your IOT Edge solution scripts code to create the environment, build the code/docker images and deploy the solution tools certificate generator and other tools for solution support .env holds environment variables that populate the generated config files from the templates deployment.debug.template.json creates a file in the /config folder called \u0026lsquo;deployment.debug.json\u0026rsquo; that populates environment variables, used for local development deployment.prod.template.json creates a file in the /config folder called \u0026lsquo;deployment.prod.json\u0026rsquo; that populates environment variables, used for production like deployment Solution Structure Overview Azure IOT Edge Devices The solution used 3 devices which will be setup in a future post.\n1. Local Simulator A simulated local environment using the Azure IoT Edge Hub Development simulator to run against the IOT Hub. When developing for the edge it is recommended not to install the real ‘IOT edge runtime’ on your machine but instead use the simulator. 2. Local Device Linux Ubuntu machine hosted in VMWare on my local machine using Hyper V https://docs.microsoft.com/bs-latn-ba/Azure/iot-edge/how-to-install-iot-edge-linux\n3. Cloud Device Linux Ubuntu hosted on Azure in our resource group created using this script This uses the pre-existing Linux Ubuntu image from the Azure Marketplace with the runtime installed.\nOnce up and running VS Code will show the devices below.\nOutro Now we have a view of the setup, development environment \u0026amp; code, we can move onto the next post ‘Developing custom modules for Azure IoT Edge’\n","permalink":"https://blog.mckelt.com/articles/posts/azure-iot-edge-who-is-cooler-dotnet-node-python/","summary":"\u003ch1 id=\"series\"\u003eSeries\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-who-is-cooler-dotnet-node-or-python-369m\" target=\"_blank\"\u003ePart 1 - dotnet vs python vs node - temperature emission - who is cooler?\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-developing-custom-modules-df3\" target=\"_blank\"\u003ePart 2 - Developing modules\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-3rd-party-containers-3mi3\" target=\"_blank\"\u003ePart 3 - Custom Containers using Apache Nifi\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-timescaledb-on-the-edge-2ec1\" target=\"_blank\"\u003ePart 4 - Custom Module using TimescaleDB\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://dev.to/chris_mckelt/azure-iot-edge-using-grafana-on-the-edge-26na\" target=\"_blank\"\u003ePart 5 - Custom Module using Grafana\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"file:///C:/temp/Part%205%20-%20Custom%20Module%20using%20Grafana\"\u003e\u003cbr\u003e\n\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"intro\"\u003eIntro\u003c/h1\u003e\n\u003cp\u003eThis code will run through creating an end to end demo of building \u0026amp; deploying an \u003ca href=\"https://docs.microsoft.com/en-us/azure/iot-edge/about-iot-edge\" target=\"_blank\"\u003eAzure IoT Edge solution\u003c/a\u003e solution.\u003c/p\u003e\n\u003cp\u003eCode for this example lives here\u003c/p\u003e\n\u003ch5 id=\"httpsgithubcomchrismckeltedgy\"\u003e\u003ca href=\"https://github.com/chrismckelt/edgy\" target=\"_blank\"\u003ehttps://github.com/chrismckelt/edgy\u003c/a\u003e\u003c/h5\u003e\n\u003ch2 id=\"what-are-we-building\"\u003eWhat are we building?\u003c/h2\u003e\n\u003cp\u003eThis solution demonstrates an air-conditioning monitoring system where 3 room sensors are publishing their temperature over time.   When a room gets too hot the air conditioner for that room is turned on. Once the room is cooled it is turned off.\u003c/p\u003e","title":"Azure IoT Edge- Who is cooler? dotnet, node or python?"},{"content":"Partnering with Spot Solutions We have partnered with a WA-based consultancy to combine our network of talented people in order to better service our clients.\nSpot Talent is our partner, providing coverage across several technology fronts.\nSpot Solutions boasts a robust network of specialists predominantly based in Australia and New Zealand. With a trusted network built over 20 years, they source talent across all experience levels—from graduates to seasoned veterans.\nTheir team of experts offers a wide range of services, including:\nFull-stack engineering Cloud architecture Data science and data engineering Product specialization They also have extensive experience working with multiple cloud platforms (Azure, AWS, GCP) and data vendors such as Databricks, Snowflake, Informatica, Alation, and dbt.\nOur Technological Competencies Could this help you? Contact me for a free discussion\n","permalink":"https://blog.mckelt.com/articles/2020/partners/","summary":"\u003ch1 id=\"partnering-with-spot-solutions\"\u003ePartnering with Spot Solutions\u003c/h1\u003e\n\u003cp\u003eWe have partnered with a WA-based consultancy to combine our network of talented people in order to better service our clients.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.spotsolutions.com.au/what-we-do\" target=\"_blank\"\u003eSpot Talent\u003c/a\u003e is our partner, providing coverage across several technology fronts.\u003c/p\u003e\n\u003cp\u003eSpot Solutions boasts a robust network of specialists predominantly based in Australia and New Zealand. With a trusted network built over 20 years, they source talent across all experience levels—from graduates to seasoned veterans.\u003c/p\u003e","title":"Partners"},{"content":"Intro Here is a quick way to setup a new WordPress blog with a custom domain on Azure (optionally using free using credits).\nAzure Resources Overview Resources used to setup the blog may be seen below. These were created within a single resource group called ‘blog’\nWordPress Setup 1. After logging into Azure go the the marketplace and search for WordPress\n2. Click create and begin to enter the details for your blog. All resources below were created in a new resource group called ‘blog’\n3. Create a new App Service Plan\nHere we are using the cheapest pricing tier that allows a custom domain: ‘B1 Basic’ Tier\n4. Configure a new database server using the ‘Basic’ pricing tier\n5. After clicking the create button a new WordPress App Service will be deployed and available to configure on YourBlogSite.azurewebsites.net\nNavigate to the website and configure your WordPress instance.\n6. Next we will setup a custom website domain to use for the blog using App Service Domains. App Service domains are custom domains that are managed directly in Azure. They make it easy to manage custom domains for Azure App Service.\nCreate your App Service Domain and choose a TLD domain name for your website.\n7. Enter your contact information required by GoDaddy for domain registration and Azure DNS to host the domains. In addition to the yearly domain registration fee, usage charges for Azure DNS apply. For information, see Azure DNS Pricing.\n8. Create you App Service Domain, it may take a while for the DNS to propagate and be ready for use\n9. Go to your App Service Domain and add a hostname binding pointing to the App Service that hosts your WordPress blog.\n10. You should now be able to browse to your custom domain and see your WordPress site. Thats it!\nConclusion So we now have a WordPress website setup with a custom domain without leaving the Azure portal.\nNext steps will be:\nCreate a free SSL certificate via Lets Encrypt to host the site under SSL Follow Azure guidelines to improve WordPress performance Please let us know how you go with setting up your own site.\nHappy blogging!\n","permalink":"https://blog.mckelt.com/articles/posts/hello-azure-wordpress-blog/","summary":"\u003ch1 id=\"intro\"\u003eIntro\u003c/h1\u003e\n\u003cp\u003eHere is a quick way to setup a new WordPress blog with a custom domain on Azure (optionally using \u003ca href=\"https://azure.microsoft.com/en-au/free\" target=\"_blank\"\u003efree using credits\u003c/a\u003e).\u003c/p\u003e\n\u003ch3 id=\"azure-resources-overview\"\u003eAzure Resources Overview\u003c/h3\u003e\n\u003cp\u003eResources used to setup the blog may be seen below. These were created within a single resource group called ‘blog’\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"images\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2021/01/1-resource-group-view.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"wordpress-setup\"\u003eWordPress Setup\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e1. After logging into Azure go the the \u003ca href=\"https://portal.azure.com/?quickstart=true\" target=\"_blank\"\u003emarketplace\u003c/a\u003e and search for WordPress\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003e\u003cimg alt=\"images\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2021/01/2-wordpress-marketplace.png\"\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e2. Click \u003cem\u003ecreate\u003c/em\u003e and begin to enter the details for your blog.  All resources below were created in a new resource group called ‘\u003cem\u003eblog’\u003c/em\u003e\u003c/p\u003e","title":"Using Azure to setup a new blog and domain"},{"content":"Often we need a fresh copy of the production database in another environment (eg DEV/TEST/UAT). Previously this was a tedious task involving getting a backup file, copying it to another location, restoring the database. Here is a solution to automate this process using Azure Pipelines.\nUser Story Given a production database exists in subscription 1 When we do a release of the Azure Pipeline named ‘_Refresh Database – DEV’_ Then an copy of production is available in the DEV environment in subscription 2 And permissions are correct for the DEV environment Pipeline Overview For each environment that you wish to restore into create an Azure Pipeline with 3 stages.\nCreate variable groups that are scoped to specific stages\nEach variable group contains deployment credentials that the specific stage will require to perform operations within the specific Azure Subscription.\nTask 1 - Export Create a PowerShell task to run a script and pass it the information for the production environment.\nThis runs against the production environment and creates a blog storage container that holds the exported BACPAC\nView code for script production-export.ps1 Results in production once this script run should show the database BACPAC export Task 2 – Import Under the ‘import’ stage create a task that will import the BACPAC from the storage container in the production subscription. This uses both production and the environment credentials.\nView code for script production-import.ps1 Task 3 – Sanitise Create a 3rd task in the ‘Sanitise’ stage. This will scramble any information you do not want in that environment (eg emails).\nAlso remove any Production SQL user account and replace them with environment specific\nView code for script sanitise Tada! Running the pipeline now copies the database to the DEV environment. Typically after this will run a software build which will automatically apply schema changes currently in DEV in the database. Happy restoring!\n","permalink":"https://blog.mckelt.com/articles/posts/using-azure-pipelines-to-restore-a-production-database-to-another-environment/","summary":"\u003cp\u003eOften we need a fresh copy of the production database in another environment (eg DEV/TEST/UAT). \u003c/p\u003e\n\u003cp\u003ePreviously this was a tedious task involving getting a backup file, copying it to another location, restoring the database.   Here is a solution to automate this process using Azure Pipelines.\u003c/p\u003e\n\u003ch3 id=\"user-story\"\u003eUser Story\u003c/h3\u003e\n\u003cpre\u003e\u003ccode\u003eGiven a production database exists in subscription 1  \nWhen we do a release of the Azure Pipeline named ‘_Refresh Database – DEV’_  \nThen an copy of production is available in the DEV environment in subscription 2  \nAnd permissions are correct for the DEV environment\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"pipeline-overview\"\u003ePipeline Overview\u003c/h2\u003e\n\u003cp\u003eFor each environment that you wish to restore into create an Azure Pipeline with 3 stages.\u003c/p\u003e","title":"Using Azure Pipelines to restore a production database to another environment"},{"content":"Cloud Adoption Framework For organisations just starting out their journey and those looking to better their governance structure, we facilitate and deliver the Microsoft Cloud Adoption Framework.\nThis will give your organisation a future plan on how to move and operate a governed Azure enterprise environment.\nTo provide optimal cloud infrastructure we will help you\n· Connect your on-premise Active Directory to Azure Active Directory (AAD) ​ · Connect your on-premise network to Azure · Setup Azure Security Centre to continuously monitor and assess your environment​\n· Re-host through PAAS/Containers/ VMs using Azure Migrate · Re-factor to serverless · Re-architect to use existing Azure services\nAzure Integration Services Azure integration services provide an enterprise ready, event-based, serverless compute experience that drives efficiency and consistency when connecting applications across the Cloud and on-premise.\nWe have expertise in enterprise messaging services and couple this with modern software design patterns focusing on serverless iPAAS (integration Platform as a Service). This allow our solutions to scale on demand and automatically react and respond to issues. Monitoring and alerting are built into the platform allowing quick identification and resolution for system failures.\nWorkload Migration We identify workloads that make sense to migrate to the cloud. Where doing so has numerous benefits from cost savings to maintainability.\nWe assess applications, networks, databases and virtual machines on benefits attained from migration and implement a plan to migrate them through the following process.\nGovernance Microsoft Cloud Services Platform\nAPI Management IaaS \u0026amp; PaaS Hybrid (cloud \u0026amp; on-premise) Application\nAPI first Microservices Serverless Web services Integration\nMicrosoft products and services (i.e. D365 CE, D365 FO, Business Central, PowerBI) Non Microsoft Services (i.e. SalesForce, HubSpot, IBM Maximo, SAP, Sage Micropay, Concur, Equifax, Green ID, Xplan) Banks - CBA, ANZ,Nab, BankStatements.com.au, Open Banking Sage Micropay Security\nApplication (OAuth, SAML, OpenID) Platform (RBAC, Policies) IAM (Identity \u0026amp; Access Management) IOT\nDevice Edge Hub Data \u0026amp; BI integration Migration\nOn-Premise to Cloud Azure DevOps ALM (Alerting, Logging \u0026amp; Monitoring)\nApplication Platform Costing DevOps Application life cycle management Continuous integration and delivery Automated testing Agile development approach MLOps ","permalink":"https://blog.mckelt.com/articles/posts/azure-service-offering-2/","summary":"\u003ch2 id=\"cloud-adoption-framework\"\u003eCloud Adoption Framework\u003c/h2\u003e\n\u003cp\u003eFor organisations just starting out their journey and those looking to better their governance structure, we facilitate and deliver the Microsoft Cloud Adoption Framework.\u003c/p\u003e\n\u003cp\u003eThis will give your organisation a future plan on how to move and operate a governed Azure enterprise environment.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//2019/07/clip_image002.jpg\" target=\"_blank\"\u003e\u003cimg alt=\"clip_image002\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/clip_image002_thumb.jpg\" title=\"clip_image002\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eTo provide optimal cloud infrastructure we will help you\u003c/p\u003e\n\u003cp\u003e· Connect your on-premise Active Directory to Azure Active Directory (AAD) ​ · Connect your on-premise network to Azure · Setup Azure Security Centre to continuously monitor and assess your environment​\u003c/p\u003e","title":"Azure Service offering"},{"content":"Intro Recently I was asked to inspect and old VB.Net Windows Forms \u0026amp; SQL Server application to see determine its future life. Part of this technical review was analysing the code base and database structure.\nTo analyse the code base I used NDepend a well-known code quality analysis tool that has progressed by leaps and bounds since I last used it on the build server circa 2013 (then version 5). Now on version 2019.2.4\nApplication Overview .Net 4.6 Windows Forms SQL Server database where most of the logic resides (some in the GUI) Setup After installing NDepend you will get a menu icon in Visual Studio\nNext setup the NDepend project for analysis. Within Visual Studio I select the projects and references I wish to include in the analysis. I am also able to include 2 extra DLLs that the vendor bundled with the application (but did not provide the source code)\nNext tab I setup the Analysis settings and output location. This will enable NDepend to perform a time-based analysis to see how the solution has progressed/regressed since the last analysis.\nRunning the Analysis The analysis tool may be run and viewed from inside Visual Studio or output as a HTML file (great for the build server report).\nApplication Metrics Quality Gates Dependency Graph Dependence Matrix Cyclomatic Complexity Cyclomatic complexity is a software metric used to indicate the complexity of a program. It is a quantitative measure of the number of linearly independent paths through a program\u0026rsquo;s source code. It was developed by Thomas J. McCabe, Sr. in 1976.\nCyclomatic complexity is computed using the control flow graph of the program: the nodes of the graph correspond to indivisible groups of commands of a program, and a directed edge connects two nodes if the second command might be executed immediately after the first command. Cyclomatic complexity may also be applied to individual functions, modules, methods or classes within a program.\nKEY AREAS TO REDUCE COMPLEXITY ARE\nCPS.UI.ProjectDataSetTableAdapters – code that handles retrieving/saving projects CPS.UI.AdminDataSetTableAdapters – code that handles retrieving/saving admin Ideally remove the use of data sets/adapters as a data access pattern and move to a modern-day best practice solution (entity framework, dapper).\nThe Abstractness versus Instability Diagram The Abstractness versus Instability Diagram helps to detect which assemblies are potentially painful to maintain (i.e concrete and stable) and which assemblies are potentially useless (i.e abstract and instable).\nAbstractness: If an assembly contains many abstract types (i.e interfaces and abstract classes) and few concrete types, it is considered as abstract.\nInstability: An assembly is considered stable if its types are used by a lot of types from other assemblies. In this context stable means painful to modify.\nOnline documentation:\nDefinitions of related Code Metrics Outro This post is a Work in Progress – stay tuned as I update it over time and determine the best use for NDepend as I have requested changes by the Vendor to fix areas of the code. NDepend will be the tool I use that helps me guide the vendors code quality.\n","permalink":"https://blog.mckelt.com/articles/posts/ndepend/","summary":"\u003ch2 id=\"intro\"\u003eIntro\u003c/h2\u003e\n\u003cp\u003eRecently I was asked to inspect and old VB.Net Windows Forms \u0026amp; SQL Server application to see determine its future life.  Part of this technical review was analysing the code base and database structure.\u003c/p\u003e\n\u003cp\u003eTo analyse the code base I used \u003ca href=\"https://www.ndepend.com/\" target=\"_blank\"\u003eNDepend\u003c/a\u003e a well-known code quality analysis tool that has progressed by \u003ca href=\"https://www.ndepend.com/release-notes\" target=\"_blank\"\u003eleaps and bounds\u003c/a\u003e since I last used it on the build server circa 2013 (then version 5).  Now on version \u003ca href=\"https://www.ndepend.com/release-notes#V2019_2_4\" target=\"_blank\"\u003e2019.2.4\u003c/a\u003e\u003c/p\u003e","title":"NDepend code analysis"},{"content":"Azure Global Bootcamp – 27th April 2019\nSlides here\n","permalink":"https://blog.mckelt.com/articles/posts/reactive-architecture-with-event-grid/","summary":"\u003cp\u003eAzure Global Bootcamp – 27th April 2019\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//2019/04/image.png\" target=\"_blank\"\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/image_thumb.png\" title=\"image\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/highres_480710988.jpeg\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.dropbox.com/s/ghutvssiyyt6otq/azure-global-bootcamp-event-grid-2019.pptx?dl=0\" target=\"_blank\"\u003eSlides here\u003c/a\u003e\u003c/p\u003e","title":"Reactive architecture with event grid"},{"content":"Reactive Architecture with Azure Event Grid Reactive, event-driven architecture Deep dive into Azure Event Grid “Take a ride on the grid” demo series 📈 Why Event Thinking Matters\nEnterprises should embrace “event thinking” as part of their digital strategy.\nBy 2020, event-sourced, real-time situational awareness will be required for 80% of digital business solutions, and 80% of new business ecosystems will require event processing. — Gartner Top 10 Strategic Technology Trends (2018)\nEvents Tell a Story\nChange is captured in an event\nA series of events captures behaviour\nEvent streams capture patterns\nTogether, they tell the narrative of the system\n⚡ What Is a Reactive Architecture?\nA system design approach focused on:\nResponsiveness Resilience Elasticity Message-driven communication More at: https://www.reactivemanifesto.org\n💬 Messages vs Commands vs Events Command\nHas intent 1-to-1 from producer → consumer Request-based Example: CreateCustomer\nEvent\nNo intent — purely a notification 1-to-many subscribers Fact-based Example: CustomerCreated\n☁️ Azure Messaging Services Overview\nAzure provides a broad messaging ecosystem including:\nService Bus Event Hubs Event Grid Storage Queues Serverless and Integration Services\n🔷 What Is Azure Event Grid?\nAzure Event Grid is a cloud-native, fully managed event routing service for building event-driven and microservice-oriented systems without heavy plumbing.\n🎯 What Is Event Grid For?\nServerless apps Ops automation Third-party integrations Azure Integration Services\n🔄 Event Grid vs Service Bus vs Event Hub\nA quick framing:\nEvent Grid → reactive notifications (push model, lightweight) Service Bus → commands, workflow coordination, reliable messaging Event Hub → large event ingestion, telemetry, streaming 📣 Why a Push Model?\nEvent Grid pushes events to subscribers as they occur, supporting system-wide reactivity.\nExample system events:\nMicrosoft.Storage.BlobCreated Microsoft.ServiceBus.ActiveMessagesAvailableWithNoListeners 🧩 Event Schemas\nEvent Grid Native Schema Standard structure used by Azure Event Grid. CloudEvents Schema An industry-standard, cloud-agnostic event schema.\nResources:\nhttps://cloudevents.io\nCNCF Serverless Working Group\nGitHub: https://github.com/cloudevents/spec\n.NET SDK: https://github.com/aliencube/CloudEvents.NET\n⚙️ Triggers\nEvent Grid can trigger:\nAzure Functions Logic Apps Automation workflows Webhooks Custom subscribers 🔐 Security\nEvent Grid supports:\nManaged identities Key authentication IP filtering Private endpoints Event domain-level access controls 📊 Event Grid – Daily Metrics\nNative monitoring includes: Delivery attempts Latency Subscriber response codes Dead-letter events 🗂️ Event Domains\nAllows multi-tenant event routing at scale, ideal for large distributed platforms.\nExcluded 6 demos done on day :( 🧪 Demo Highlights Demo 1\nRide the grid: event publishing and subscriptions.\nDemo 2\nLive event monitoring 🔗 https://eventsmonitoring2019.azurewebsites.net/\nDemo 3\n_Microsoft Flow integration. _ Demo 4\nDumb insurance claim management flow\nExample pattern:\n_Inbound API request → publish event _ Event subscriber → execute command\nEvent publisher → emit result event\nMultiple subscribers react\n🏗️ Claim Entity Event Flow Example\nFor each Claim:\nClaim has a Status\nBusiness process flows trigger on status changes\nStatus updates broadcast events\nMicroservices react and write back updates\nBPF rules trigger again from field updates\nReactive loops power distributed workflows.\nThanks \u0026amp; remember \u0026lsquo;#PushDontPull\u0026rsquo; 🙌 Images\n","permalink":"https://blog.mckelt.com/articles/2019/reactive-architecture-with-azure-event-grid/","summary":"\u003ch2 id=\"reactive-architecture-with-azure-event-grid\"\u003eReactive Architecture with Azure Event Grid\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eReactive, event-driven architecture\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDeep dive into Azure Event Grid\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e“Take a ride on the grid” demo series\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cimg   src=\"https://github.com/user-attachments/assets/a0b783df-80e6-4e7c-a796-a95fea691512\" /\u003e\n\u003cp\u003e📈 Why Event Thinking Matters\u003c/p\u003e\n\u003cp\u003eEnterprises should embrace “event thinking” as part of their digital strategy.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eBy 2020, event-sourced, real-time situational awareness will be required for 80% of digital business solutions, and 80% of new business ecosystems will require event processing.\n— Gartner Top 10 Strategic Technology Trends (2018)\u003c/p\u003e","title":"Reactive Architecture with Azure Event Grid"},{"content":"Overview on how to publish data entity changes from Dynamics Finance and Operations to Azure Event Grid. Step 1 In D365FO, Navigate to the Business Events Catalogue page\nStep 2 Navigate to the endpoints tab and select ‘Azure Event Grid’\nStep 3 In Azure, create an application service registration\nTake note of the Application Id and the Secret Id\nStep 4 In Azure, create an Azure Event Grid Topic\nhttps://customers.westus2-1.eventgrid.azure.net/api/events\nCopy the Access Key\nStep 5 In Azure, create an Azure Key Vault with a key called\nkey-eventgrid-topic-d365fo-customers\nThe secret value is the Access Key for the Event Grid Topic\nStep 6 On the key vault – grant access to the secret for the Application Registration\nStep 7 In D365FO ‘configure an endpoint’ and enter the Azure Event Grid Topic endpoint\nIt now requires the Application Id \u0026amp; Application secret + the key vault name + name of secret in key vault (to get the Access Key)\nStep 8 An endpoint should now display\nStep 9 Activate the following 2 business events\nBusinessEventsAlertEvent BusinessEventsDueDateAlertEvent select your newly created endpoint\nStep 10 From the customers list, create a custom alert\nConfigure the alert to happen when the record is created, deleted or a field changes\nEnsure ‘Send Externally’ is true\nStep 11 Edit the customer and change the field with the alert on it \u0026amp; save the record\nStep 12 view an alert \u0026amp; business event arrives in the following table\nhttps://XXXXX.dynamics.com/Default.htm?mi=SysTableBrowser\u0026amp;cmp=YYYY\u0026amp;tablename=eventcud\nXXXXX == your organisations URL\nYYYY == your company\nif no record appears here – you might need to fix your batch jobs\nStep 13 Verify that your Azure Event Grid Topic has received the customer change events\nStep 14 The below payload structure is sent to Event Grid\nSubscribing to published Events in Flow Sample extract (which was pushed to teams) ID = BULK-002 Event = LocationChanged Payload = {\u0026ldquo;BusinessEventId\u0026rdquo;:\u0026ldquo;BusinessEventsAlertEvent\u0026rdquo;,\u0026ldquo;ControlNumber\u0026rdquo;:5637145330,\u0026ldquo;Email\u0026rdquo;:\u0026ldquo;Chris.McKelt@xxx.com.au\u0026rdquo;,\u0026ldquo;EventId\u0026rdquo;:\u0026ldquo;D60A8657-E87C-43A8-8D7D-826EBF0490D7\u0026rdquo;,\u0026ldquo;EventTime\u0026rdquo;:\u0026quot;/Date(1570769681000)/\u0026quot;,\u0026ldquo;FieldId\u0026rdquo;:3,\u0026ldquo;Link\u0026rdquo;:\u0026quot;\u0026quot;,\u0026ldquo;MajorVersion\u0026rdquo;:0,\u0026ldquo;Message\u0026rdquo;:\u0026ldquo;LocationChanged\u0026rdquo;,\u0026ldquo;MessageDetails\u0026rdquo;:\u0026ldquo;View Location: BULK-002, 24\u0026rdquo;,\u0026ldquo;MinorVersion\u0026rdquo;:0,\u0026ldquo;ParentTableId\u0026rdquo;:8565,\u0026ldquo;RuleId\u0026rdquo;:\u0026ldquo;000428\u0026rdquo;,\u0026ldquo;Subject\u0026rdquo;:\u0026ldquo;LocationChanged\u0026rdquo;,\u0026ldquo;TableId\u0026rdquo;:8565,\u0026ldquo;TypeTrigger\u0026rdquo;:\u0026ldquo;FieldChanged\u0026rdquo;,\u0026ldquo;UserId\u0026rdquo;:\u0026ldquo;Chris.McKelt\u0026rdquo;} Key Points for setting up change alerts in D365 FO\nAlerts should be setup under 1 user with admin permissions (on test this is the dual write user) Setup a Batch Group called INT (integration) and allocate servers to it Ensure the Batch Job is setup as below (note the user) Exported Logic App / Flow Example to listen to events and send to Teams channel ","permalink":"https://blog.mckelt.com/articles/posts/configure-d365-fo-and-event-grid/","summary":"\u003ch3 id=\"overview-on-how-to-publish-data-entity-changes-from-dynamics-finance-and-operations-to-azure-event-grid\"\u003eOverview on how to publish data entity changes from Dynamics Finance and Operations to Azure Event Grid.\u003c/h3\u003e\n\u003ch3 id=\"step-1\"\u003eStep 1\u003c/h3\u003e\n\u003cp\u003eIn D365FO, Navigate to the Business Events Catalogue page\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2019/10/image.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"step-2\"\u003eStep 2\u003c/h3\u003e\n\u003cp\u003eNavigate to the \u003cem\u003eendpoints\u003c/em\u003e tab and select ‘Azure Event Grid’\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2019/10/image-1.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"step-3\"\u003eStep 3\u003c/h3\u003e\n\u003cp\u003eIn Azure, create an application service registration\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2019/10/image-2.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eTake note of the Application Id and the Secret Id\u003c/em\u003e\u003c/p\u003e\n\u003ch3 id=\"step-4\"\u003eStep 4\u003c/h3\u003e\n\u003cp\u003eIn Azure,  create an Azure Event Grid Topic\u003c/p\u003e","title":"Configure D365 fo and event grid"},{"content":"To create the D365 FinOps C# OData Proxy do: 1. Install the following plugin\nhttps://marketplace.visualstudio.com/items?itemName=Unchase.unchaseodataconnectedservice\n2. Using a Visual Studio Standard Library project and add a new ‘Connected Service’\n3. Open the Reference.cs file in VS Code (VS Code seems to handle the file better than Notepad++ and Visual Studio)\n4. Search for the EDMX mega string in the file\nprivate const string Edmx = @”[mega big xml string we need to change]”\n5. Cut the EDMX mega string and place in a file on disk call edmx.xml on disk. Change \u0026quot;\u0026quot; to \u0026quot;\nSet this to be file to be embedded content in your Visual Studio project\n5. Search for the below function name and replace with the code below:\n6. Now create your own proxy wrapper with authentication using:\n7. Sample unit test to create a sales order\n","permalink":"https://blog.mckelt.com/articles/posts/d365-fo-odata-proxy-generation/","summary":"\u003ch2 id=\"to-create-the-d365-finops-c-odata-proxy-do\"\u003eTo create the D365 FinOps C# OData Proxy do:\u003c/h2\u003e\n\u003cp\u003e1. Install the following plugin\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://marketplace.visualstudio.com/items?itemName=Unchase.unchaseodataconnectedservice\" target=\"_blank\"\u003ehttps://marketplace.visualstudio.com/items?itemName=Unchase.unchaseodataconnectedservice\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e2. Using a Visual Studio Standard Library project and add a new ‘Connected Service’\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2019/12/clip_image0014.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2019/12/clip_image0024.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2019/12/image.png\"\u003e\u003c/p\u003e\n\u003cp\u003e3. Open the \u003cem\u003eReference.cs\u003c/em\u003e  file in VS Code (\u003cem\u003eVS Code seems to handle the file better than Notepad++ and Visual Studio)\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e4.  Search for the EDMX mega string in the file\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eprivate const string Edmx  = @”[mega big xml string we need to change]”\u003c/em\u003e\u003c/p\u003e","title":"D365 FO OData proxy generation"},{"content":"Predicting BS using ML.Net Machine learning is typically the realm for R/Python. But can .Net move into this space?\nIn this talk we will run through Microsoft\u0026rsquo;s new ML.Net framework including what it currently offers, how to build a learning pipeline and how to deploy a model to an Azure Service.\nhttps://slides.com/chrismckelt/deck-451cdb94-a37d-47b7-9d49-6686065e7d03\n","permalink":"https://blog.mckelt.com/articles/posts/perth-net-user-group-talk/","summary":"\u003ch1 id=\"predicting-bs-using-mlnet\"\u003ePredicting BS using ML.Net\u003c/h1\u003e\n\u003cp\u003eMachine learning is typically the realm for R/Python. But can .Net move into this space?\u003c/p\u003e\n\u003cp\u003eIn this talk we will run through Microsoft\u0026rsquo;s new ML.Net framework including what it currently offers, how to build a learning pipeline and how to deploy a model to an Azure Service.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//2018/08/image-7.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://slides.com/chrismckelt/deck-451cdb94-a37d-47b7-9d49-6686065e7d03\" title=\"https://slides.com/chrismckelt/deck-451cdb94-a37d-47b7-9d49-6686065e7d03\" target=\"_blank\"\u003ehttps://slides.com/chrismckelt/deck-451cdb94-a37d-47b7-9d49-6686065e7d03\u003c/a\u003e\u003c/p\u003e\n\u003ciframe width=\"576\" height=\"420\" src=\"//slides.com/chrismckelt/deck-451cdb94-a37d-47b7-9d49-6686065e7d03/embed?style=dark\u0026amp;byline=hidden\u0026amp;share=hidden\" frameborder=\"0\" scrolling=\"no\" allowfullscreen mozallowfullscreen=\"\" webkitallowfullscreen=\"\"\u003e\u003c/iframe\u003e","title":"Perth .Net user group talk"},{"content":"In the previous post we built a machine learning model using ML.Net, in this post we will deploy the model to an Azure app and allow it to be used via a HTTP API\nUsing the output model in zip format ‘vita-model-1.zip’ we can include this in our web application as an embedded resource or simply include the file for deployment.\nTo use the file from a HTTP endpoint:\nInclude the zip file in your deployment – embedded resource/content/read from blob storage etc.. Initialise the model as a singleton during application start up by using a file path or stream Call the model using the function PredictionModel.Predict(‘my data from which to predict’) Sample below that logs to Logz.io\n[Produces(\u0026#34;application/json\u0026#34;)] [Route(\u0026#34;[controller]\u0026#34;)] public class PredictionController : Controller { private readonly IPredict _predictor; public PredictionController(IPredict predictor) { _predictor = predictor; } [HttpPost(\u0026#34;predict\u0026#34;)] [SwaggerResponse(HttpStatusCode.OK, typeof(string))] public async Task\u0026lt;IActionResult\u0026gt; Search(PredictionRequest request) { Guard.AgainstNull(request); var requestId = Guid.NewGuid(); using (LogContext.PushProperty(\u0026#34;request\u0026#34;, request.ToJson())) using (LogContext.PushProperty(\u0026#34;requestId\u0026#34;, requestId)) { try { var result = await _predictor.PredictAsync(request); return Ok(result); } catch (Exception e) { Console.WriteLine(e); Log.Warning(e, \u0026#34;PredictionController error {request}\u0026#34;, request.ToJson()); return NoContent(); } } } } Hosting our endpoint with Swagger on Azure allows us to test the inputs and see the results below:\nT\nConclusion Here we hosted our model in Azure using an App Service and managed to test it via Swagger.\nHoping to make this a Function App when this issue is resolved –\u0026gt; https://github.com/dotnet/machinelearning/issues/569\nCode https://github.com/chrismckelt/vita\n","permalink":"https://blog.mckelt.com/articles/posts/charge-id-deploying-to-a-ml-net-model-to-azure-part-6/","summary":"\u003cp\u003eIn the previous post we built a machine learning model using \u003ca href=\"http://dot.net/ml\" target=\"_blank\"\u003eML.Net\u003c/a\u003e, in this post we will deploy the model to an Azure app and allow it to be used via a HTTP API\u003c/p\u003e\n\u003cp\u003eUsing the output model in zip format ‘vita-model-1.zip’ we can include this in our web application as an embedded resource or simply include the file for deployment.\u003c/p\u003e\n\u003cp\u003eTo use the file from a HTTP endpoint:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eInclude the zip file in your deployment – embedded resource/content/read from blob storage etc..\u003c/li\u003e\n\u003cli\u003eInitialise the model as a singleton during application start up by using a file path or stream\u003c/li\u003e\n\u003cli\u003eCall the model using the function PredictionModel.Predict(‘my data from which to predict’)\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eSample below that logs to \u003ca href=\"https://logz.io/\" target=\"_blank\"\u003eLogz.io\u003c/a\u003e\u003c/p\u003e","title":"Charge Id - Deploying a ML.Net Model to Azure"},{"content":"In this post we will build a prediction model using ML .Net to classify an individual bank transaction into a pre-defined group using the description text.\nWe will then evaluate the effectiveness of the model using standard evaluation metrics.\nThe steps involved to create a model using ML.Net are:\nDecide what type of machine learning problem we are trying to solve? Retrieve and clean the data (CSV/TSV used with ML.Net for no) Create a prediction service API Create a ‘Learning Pipeline’ to iterate over the model build process Training Testing Evaluating result metrics Exploring the output model file Deciding what type of machine learning problem we are trying to solve? This cheat sheet is a good place to start to help identify the type of outcome you want from the data you have.\nIn this area we are using Supervised machine learning to predict a single category given an input of data [TransactionUtcDate, Description, Amount].\nAs we have a known set of categories (known set of labels) we will be using a multi class classifier which is described as follows:\nMulti-Class: classification task with more than two classes such that the input is to be classified into one, and only one of these classes. Example: classify a set of images of fruits into any one of these categories — apples,bananas, and oranges. Other types available are:\nMulti-labels: classifying a sample into a set of target labels. Example: tagging a blog into one or more topics like technology, religion, politics etc. Labels are isolated and their relations are not considered important. Hierarchical: each category can be grouped together with similar categories, creating meta-classes, which in turn can be grouped again until we reach the root level (set containing all data). Examples include text classification\u0026amp; species classification. Retrieving and cleaning the data Having analysed the data and problem we now have an CSV extract for a bank account statement.\nWe shuffle the data in the file and split this into 2 files ‘train.csv’ and ‘test.csv’ in order to perform cross validation.\nCreating a prediction service To use our predictor we create a prediction service with 3 methods:\npublic interface IPredict { Task\u0026lt;string\u0026gt; PredictAsync(PredictionRequest request); Task\u0026lt;string\u0026gt; TrainAsync(string trainpath); Task\u0026lt;ClassificationMetrics\u0026gt; EvaluateAsync(string testPath); } Creating the Learning Pipeline var pipeline = new LearningPipeline { // load from CSV --\u0026gt; SubCategory manually classified), Description, Bank, Amount, AccountName, Notes, Tags new TextLoader(trainpath).CreateFrom\u0026lt;BankStatementLineItem\u0026gt;(separator: \u0026#39;,\u0026#39;, useHeader: true), new Dictionarizer((\u0026#34;SubCategory\u0026#34;, \u0026#34;Label\u0026#34;)), //Converts input values (words, numbers, etc.) to index in a dictionary. // ngram analysis over the transaction description new TextFeaturizer(\u0026#34;Description\u0026#34;, \u0026#34;Description\u0026#34;) { TextCase = TextNormalizerTransformCaseNormalizationMode.Lower, WordFeatureExtractor = new NGramNgramExtractor(){Weighting = NgramTransformWeightingCriteria.TfIdf} }, new TextFeaturizer(\u0026#34;Bank\u0026#34;, \u0026#34;Bank\u0026#34;) { TextCase = TextNormalizerTransformCaseNormalizationMode.Lower }, // feature column using bank and description new ColumnConcatenator(\u0026#34;Features\u0026#34;, \u0026#34;Bank\u0026#34;, \u0026#34;Description\u0026#34;), //The SDCA method combines several of the best properties and capabilities of logistic regression and SVM algorithms new StochasticDualCoordinateAscentClassifier(){Shuffle = false, NumThreads = 1}, //Transforms a predicted label column to its original values, unless it is of type bool new PredictedLabelColumnOriginalValueConverter() {PredictedLabelColumn = \u0026#34;PredictedLabel\u0026#34;} }; Training\nConsole.WriteLine(\u0026#34;=============== Start training ===============\u0026#34;); var watch = System.Diagnostics.Stopwatch.StartNew(); _model = pipeline.Train\u0026lt;BankStatementLineItem, PredictedLabel\u0026gt;(); await _model.WriteAsync(PredictorSettings.Model1Path); watch.Stop(); Console.WriteLine($\u0026#34;=============== End training ===============\u0026#34;); Console.WriteLine($\u0026#34;training took {watch.ElapsedMilliseconds} milliseconds\u0026#34;); Console.WriteLine(\u0026#34;The model is saved to {0}\u0026#34;, PredictorSettings.Model1Path); Testing\npublic async Task\u0026lt;string\u0026gt; PredictAsync(PredictionRequest request) { if (_model == null) { _model = await PredictionModel.ReadAsync\u0026lt;BankStatementLineItem, PredictedLabel\u0026gt;(PredictorSettings.Model1Path); } var item = new BankStatementLineItem { Description = request.Description, AccountName = request.AccountName, Amount = request.Amount, AccountNumber = request.AccountNumber, Bank = request.Bank, TransactionUtcDate = request.TransactionUtcDate, Notes = request.Notes, Tags = request.Tags }; var prediction = _model.Predict(item); return prediction.SubCategory; } Write an test for verify subcategories are correctly predicted from the test data [Theory] [InlineData(\u0026#34;EFTPOS ALDI 27 CARRUM DOWNS AU\u0026#34;,\u0026#34;ANZ\u0026#34;,Categories.Groceries.Supermarkets)] [InlineData(\u0026#34;Kmart Cannington Aus\u0026#34;,\u0026#34;ANZ\u0026#34;,Categories.Shopping.OtherShopping)] [InlineData(\u0026#34;Bunnings Innaloo\u0026#34;,\u0026#34;ANZ\u0026#34;,Categories.Home.HomeImprovement)] [InlineData(\u0026#34;City Of Perth Park1 Perth\u0026#34;,\u0026#34;ParkingTolls\u0026#34;,Categories.Transport.ParkingTolls)] [InlineData(\u0026#34;Virgin Australia Airli Spring Hill Aus\u0026#34;,\u0026#34;WESTPAC_INTERNET_BANKING\u0026#34;,Categories.HolidayTravel.Flights)] [InlineData(\u0026#34;My Healthy Place Floreat\u0026#34;,\u0026#34;WESTPAC_INTERNET_BANKING\u0026#34;,Categories.HealthBeauty.Chemists)] public async Task Predict_test_sample(string description, string bank, string subcategory) { var result = await _predict.PredictAsync(new PredictionRequest() { Description = description, Bank =bank }); Console.WriteLine(result); result.Should().Be(subcategory); } Evaluating result metrics public async Task\u0026lt;ClassificationMetrics\u0026gt; EvaluateAsync(string testPath) { var testData = new TextLoader(testPath).CreateFrom\u0026lt;BankStatementLineItem\u0026gt;(separator: \u0026#39;,\u0026#39;, useHeader: true); var evaluator = new ClassificationEvaluator(); if (_model == null) { _model = await PredictionModel.ReadAsync\u0026lt;BankStatementLineItem, PredictedLabel\u0026gt;(PredictorSettings.Model1Path); } var metrics = evaluator.Evaluate(_model, testData); return metrics; } Write a test to ensure the model is giving accurate results\n[Fact] public async Task Evaluate_accuracy_greater_than_95_percent() { var metrics = await _predict.EvaluateAsync(Test); Console.WriteLine(); Console.WriteLine(\u0026#34;PredictionModel quality metrics evaluation\u0026#34;); Console.WriteLine(\u0026#34;------------------------------------------\u0026#34;); Console.WriteLine($\u0026#34;confusion matrix: {metrics.ConfusionMatrix}\u0026#34;); metrics.AccuracyMacro.Should().BeGreaterOrEqualTo(0.95); } The output metrics Metrics for classification models The following metrics are reported when evaluating classification models. If you compare models, they are ranked by the metric you select for evaluation.\nAccuracyMacro The macro-average is computed by taking the average over all the classes of the fraction of correct predictions in this class (the number of correctly predicted instances in the class, divided by the total number of instances in the class).\nThe macro-average metric gives the same weight to each class, no matter how many instances from that class the dataset contains.\nAccuarcyMicro The micro-average is the fraction of instances predicted correctly. The micro-average metric weighs each class according to the number of instances that belong to it in the dataset.\nLogLoss The log-loss metric, is computed as follows: LL = - (1/m) * sum( log(p[i])) where m is the number of instances in the test set. p[i] is the probability returned by the classifier if the instance belongs to class 1, and 1 minus the probability returned by the classifier if the instance belongs to class 0.\nLogLossReduction The log-loss reduction is scaled relative to a classifier that predicts the prior for every example: (LL(prior) - LL(classifier)) / LL(prior) This metric can be interpreted as the advantage of the classifier over a random prediction. E.g., if the RIG equals 20, it can be interpreted as \u0026ldquo;the probability of a correct prediction is 20% better than random guessing\u0026rdquo;.\nPerClassLogLoss The log-loss metric, is computed as follows: LL = - (1/m) * sum( log(p[i])) where m is the number of instances in the test set. p[i] is the probability returned by the classifier if the instance belongs to the class, and 1 minus the probability returned by the classifier if the instance does not belong to the class.\nTopKAccuracy\nIf OutputTopKAcc was specified on the evaluator to be k, then TopKAccuracy is the relative number of examples where the true label is one of the top k predicted labels by the predictor.\nExploring the output model file The model is output as a .zip file making it easy to deploy.\nExtracted contents are below\nConclusion In this post we have chosen a machine learning model to create, built a learning pipeline to ingest the data, performed training and evaluated our metrics using training data. The end result is a deployable file alongside our application.\nNext up –\u0026gt; hosting the model in an Azure Function app. Code https://github.com/chrismckelt/vita\n","permalink":"https://blog.mckelt.com/articles/posts/charge-id-building-the-prediction-models-part-5/","summary":"\u003cp\u003eIn this post we will build a prediction model using ML .Net to classify an individual bank transaction into a pre-defined group using the description text.\u003c/p\u003e\n\u003cp\u003eWe will then evaluate the effectiveness of the model using standard evaluation \u003ca href=\"https://docs.microsoft.com/en-us/dotnet/machine-learning/resources/glossary\" target=\"_blank\"\u003emetrics\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThe steps involved to create a model using ML.Net are:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eDecide what type of machine learning problem we are trying to solve?\u003c/li\u003e\n\u003cli\u003eRetrieve and clean the data   (CSV/TSV used with ML.Net for no)\u003c/li\u003e\n\u003cli\u003eCreate a prediction service API\u003c/li\u003e\n\u003cli\u003eCreate a ‘Learning Pipeline’ to iterate over the model build process\n\u003cul\u003e\n\u003cli\u003eTraining\u003c/li\u003e\n\u003cli\u003eTesting\u003c/li\u003e\n\u003cli\u003eEvaluating result metrics\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eExploring the output model file\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e \u003c/p\u003e","title":"Charge Id – The prediction model"},{"content":"So what are we trying to do here? Hypothesis Given a users bank statement we will be able to predict (within a statistical confidence level ) the transactions within a period into categories \u0026amp; sub categories for spending classification.\nTarget Categories Banking \u0026amp; Finance Entertainment Food \u0026amp; Drinks Groceries Health \u0026amp; Beauty Holiday \u0026amp; Travel Home Household Utilities Income Insurance Kids Miscellaneous Shopping Transferring Money Transport Work \u0026amp; Study Sub categories available on this link\nSo what does a bank statement usually contain? Account Summary Account Statement Account Transactions Account types come in numerous varieties of credit/debit options.\nWhat data are we trying to predict? Each transaction will contain at least 3 lines which can be used for categorisation prediction.\nTransaction date Transaction line description Amount We want to know whether the payment was debit/credit and for what reason. So we can analyse our/the consumers financial decisions overtime. Not all categories will be easy. Random text entered by the vendor can stop a transaction type being identified easily.\nBut there are other ways to predict what that type of transaction would be. For example, given an unclassified transaction (not recognisable by keywords such as café, food, bar) occurred on a Saturday night between 5-10pm with the amount \u0026gt; 20 and under 500 the algorithm will look at past consumer payments at this time period and see most common categories at this time are food/restaurants/bars. PS let me know if you spend close to $500 on a bar bill – I think I want to party with you!\nFrom this we are looking to summate the transactions for each sub category into their parent group.\nBelow is a result of manually classifying 3 months worth of bank statements into assigned categories.\nSample of Subcategories having \u0026gt; 50 occurrences on a bank statement\nEach sub-category rolls up into its parent category which gives a clearer view on where money is coming/going: Total categories summed by subcategory\nSumming the amount for each of these categories will give us the total income/expenditure. Posts in this series Charge Id – scratching the tech itch Charge Id – lean canvas\nCharge Id – solution overview\nCharge Id – analysing the data\nCharge Id – the prediction model\nCharge Id – deploying a ML.Net Model to Azure\nCode https://github.com/chrismckelt/vita\n","permalink":"https://blog.mckelt.com/articles/posts/charge-id-analysing-the-data-part-4/","summary":"\u003ch2 id=\"so-what-are-we-trying-to-do-here\"\u003eSo what are we trying to do here?\u003c/h2\u003e\n\u003ch3 id=\"hypothesis\"\u003eHypothesis\u003c/h3\u003e\n\u003cp\u003eGiven a users bank statement we will be able to predict (within a statistical confidence level ) the transactions within a period into \u003ca href=\"https://github.com/chrismckelt/vita/blob/master/source/Vita.Contracts/SubCategories/Categories.cs\" target=\"_blank\"\u003ecategories \u0026amp; sub categories\u003c/a\u003e for spending classification.\u003c/p\u003e\n\u003ch3 id=\"target-categories\"\u003eTarget Categories\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eBanking \u0026amp; Finance\u003c/li\u003e\n\u003cli\u003eEntertainment\u003c/li\u003e\n\u003cli\u003eFood \u0026amp; Drinks\u003c/li\u003e\n\u003cli\u003eGroceries\u003c/li\u003e\n\u003cli\u003eHealth \u0026amp; Beauty\u003c/li\u003e\n\u003cli\u003eHoliday \u0026amp; Travel\u003c/li\u003e\n\u003cli\u003eHome\u003c/li\u003e\n\u003cli\u003eHousehold Utilities\u003c/li\u003e\n\u003cli\u003eIncome\u003c/li\u003e\n\u003cli\u003eInsurance\u003c/li\u003e\n\u003cli\u003eKids\u003c/li\u003e\n\u003cli\u003eMiscellaneous\u003c/li\u003e\n\u003cli\u003eShopping\u003c/li\u003e\n\u003cli\u003eTransferring Money\u003c/li\u003e\n\u003cli\u003eTransport\u003c/li\u003e\n\u003cli\u003eWork \u0026amp; Study\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/chrismckelt/vita/blob/master/source/Vita.Contracts/SubCategories/Categories.cs\" target=\"_blank\"\u003eSub categories available on this link\u003c/a\u003e\u003c/p\u003e","title":"Charge Id – Analysing the data"},{"content":"The proposed solution sequence flow follows:\nPosts in this series Charge Id – scratching the tech itch Charge Id – lean canvas\nCharge Id – solution overview\nCharge Id – analysing the data\nCharge Id – the prediction model\nCharge Id – deploying a ML.Net Model to Azure\nCode https://github.com/chrismckelt/vita\n","permalink":"https://blog.mckelt.com/articles/posts/charge-id-solution-overview-part-3/","summary":"\u003cp\u003eThe proposed solution sequence flow follows:\u003c/p\u003e\n\u003ch3 id=\"heading\"\u003e \u003cimg loading=\"lazy\" src=\"https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgQ2hhcmdlSWQgT3ZlcnZpZXcKClVzZXItPiBXZWIgQVBJIDogdGV4dCBpZGVudGlmaWNhdGlvbiByZXF1ZXN0Cm5vdGUgbGVmdCBvZgArCDogIGF1dGhlbnQAJwcKAEQILT4gQ29zbW9zIERCOiBsb29rdXAgY2xhc3NpZmllZCBjAIEJBXMgCgAdCSAtPiBVc2VyIDogZm91bmQgbWF0Y2gAFgotPiBDADoGeSBwaXBlbGluZSA6IG5vdAAqBgoADREtPiBQcmVkaWMAgUMFAIFcBnAACwYKAAoPLQCBJAwAHQplZCAAgWoOAHEROiAgYWRkIHRvIEF6dXJlIGVsYXN0aWMgc2VhcmNoIGNsdXN0ZXIAgUUhAIEZDyAAgwkNbm8AggUHAIJ-BXJpZ2gAgnUPc2VuAH4FcXVldWUgZm9yIG1hbnVhbCBwcm9jZXNzaW5nAIIKFACBOhNyZS10cmFpbiBtb2RlbAoK\u0026s=napkin\"\u003e\u003c/h3\u003e\n\u003chr\u003e\n\u003ch2 id=\"posts-in-this-series\"\u003ePosts in this series\u003c/h2\u003e\n\u003cp\u003eCharge Id – scratching the tech itch \u003cbr\u003e\nCharge Id – lean canvas\u003cbr\u003e\nCharge Id – solution overview\u003cbr\u003e\nCharge Id – analysing the data\u003cbr\u003e\nCharge Id – the prediction model\u003cbr\u003e\nCharge Id – deploying a ML.Net Model to Azure\u003c/p\u003e\n\u003ch2 id=\"code\"\u003eCode\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/chrismckelt/vita\" title=\"https://github.com/chrismckelt/vita\" target=\"_blank\"\u003ehttps://github.com/chrismckelt/vita\u003c/a\u003e\u003c/p\u003e","title":"Charge Id – solution overview"},{"content":"Lean Canvas Problem This is the start of a series of blog posts where I try to build an online personal budgeting system.\nThe motivation for this was me trying to do a household budget usin\nWith Open Banking approaching a common service to classify income and expenditure for bank statement transactions is not currently available on the market.\nThe ability for a consumer to categorise their transactions sits within varied personal finance providers (eg. pocketbook, mint).\nSolution An API that uses Named Entity Recognition to identifies a consumers bank statement into the below groups:\nWhy –\u0026gt; classification (eg Holiday travel) \u0026amp; sub-category (flights) Who –\u0026gt; company originating the charge When –\u0026gt; Date time \u0026amp; location How –\u0026gt; Method of transfer (EftPos, cash withdraw, direct debit, credit card) What –\u0026gt; Type of transaction is it? Dishonour, Overdrawn, Interest, Fees, Credit, Debit\n-\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;-\nKey Metrics Correct classifications API Usage Website signups Website classification requests Percent of statements marked as correct (accurately identified) Unique Value Proposition We offer an open solution to personal financial statement classification. Similar products pocketbook – automated classification pocketsmith.com – automated classification youneedabudget.com – manual classification myprosperity.com.au - – manual classification Mint – US based no AU presence Difference We use online machine learning to classify all transactions on a bank statement and categorise them into categories for visualisation.\nPotential future features Personal finance advice Weekly email summary statement of financial portfolio Fraud alerts Better products alert (mortgage/insurance) Tax savings calculator \u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026ndash; Channels Free for consumers. Paid for financial institutions that want to use the API\nCustomer Segments Retail consumers wanting to understand their financial statement Business consumers wanting financial insight into their customers\nCost Structure Free for website use API cost Posts in this series Charge Id – scratching the tech itch Charge Id – lean canvas\nCharge Id – solution overview\nCharge Id – analysing the data\nCharge Id – the prediction model\nCharge Id – deploying a ML.Net Model to Azure\nCode https://github.com/chrismckelt/vita\n","permalink":"https://blog.mckelt.com/articles/posts/charge-id-lean-canvas-part-2/","summary":"\u003ch1 id=\"lean-canvas\"\u003eLean Canvas\u003c/h1\u003e\n\u003ch2 id=\"problem\"\u003eProblem\u003c/h2\u003e\n\u003cp\u003eThis is the start of a series of blog posts where I try to build an online personal budgeting system.\u003c/p\u003e\n\u003cp\u003eThe motivation for this was me trying to do a household budget usin\u003c/p\u003e\n\u003cp\u003eWith \u003ca href=\"https://en.wikipedia.org/wiki/Open_banking\" target=\"_blank\"\u003eOpen Banking\u003c/a\u003e approaching a common service to classify income and expenditure for bank statement transactions is not currently available on the market.\u003c/p\u003e\n\u003cp\u003eThe ability for a consumer to categorise their transactions sits within varied personal finance providers (eg. pocketbook, mint).\u003c/p\u003e","title":"Charge Id - Lean Canvas"},{"content":"This is the start of a series of blog posts where I try to build an online personal budgeting system.\nThe motivation for this was me trying to do a household budget using existing tools (Pocketbook, CashDesk, QuickBooks, Xero).\nEach time I needed to classify a large number of transactions manually (except Pocketbook they have got a pretty good classification engine)\nAs I do lots of transfer between accounts the summaries never made sense. So I thought Id give it a go to build my own personal finance budgeter.\nGoals Discover the Who, What When, Where, Why and How a money transaction occurred purely from the metadata Website that allows users to connect/upload their bank accounts Connect to a users bank account using bankstatements.com.au / basiq.io (hoping to switch to Open Banking OAuth when available) Classify bank statements into categories \u0026amp; sub categories Summarise personal finances and display to a consumable way Predict spend over time \u0026amp; necessary budgeting Find savings / tax deductions (mortgage, insurance etc) The code for this solution is hosted on GitHub https://github.com/chrismckelt/vita\nPosts in this series Charge Id – scratching the tech itch\nCharge Id – lean canvas\nCharge Id – solution overview\nCharge Id – analysing the data\nCharge Id – the prediction model\nCharge Id – deploying a ML.Net Model to Azure\nCode https://github.com/chrismckelt/vita\n","permalink":"https://blog.mckelt.com/articles/posts/open-startup-scratching-the-itch-to-solve-my-own-problem-through-tech/","summary":"\u003cp\u003eThis is the start of a series of blog posts where I try to build an online personal budgeting system.\u003c/p\u003e\n\u003cp\u003eThe motivation for this was me trying to do a household budget using existing tools (Pocketbook, CashDesk, QuickBooks, Xero).\u003c/p\u003e\n\u003cp\u003eEach time I needed to classify a large number of transactions manually (except Pocketbook they have got a pretty good classification engine)\u003c/p\u003e\n\u003cp\u003eAs I do lots of transfer between accounts the summaries never made sense.  So I thought Id give it a go to build my own personal finance budgeter.\u003c/p\u003e","title":"Charge Id – What is the problem?"},{"content":" https://www.rpubs.com/chris_mckelt/capstone-presentation\n","permalink":"https://blog.mckelt.com/articles/posts/word-prediction-with-natural-language-processing/","summary":"\u003ch3\u003e\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"https://www.rpubs.com/chris_mckelt/capstone-presentation\" target=\"_blank\"\u003ehttps://www.rpubs.com/chris_mckelt/capstone-presentation\u003c/a\u003e\u003c/p\u003e","title":"Word prediction with Natural Language Processing"},{"content":"After initially using Trello with ‘Scrum for Trello’\u0026rsquo; to run our companies Agile process and having to manually create burn downs and release estimates with Excel (after mangling data from the Trello API and a Google Spread sheet) we moved to Trello with GetCorrello (and switched to Kanban after a few months with the teams consent)\nCharts from this tool are below. The GetCorrello team were able to add features on demand. Would use them again!\nhttps://getcorrello.com\nSome samples Burndown Cumulative Flow Diagram Estimated time to complete per label Control chart Cycle times Stats Slack integration Our Kanban process https://www.dropbox.com/s/fj1mr93gqhxv8nc/Fair%20Go%20Kanban%20Process.pptx?dl=0\n","permalink":"https://blog.mckelt.com/articles/posts/trello-with-getcorrello-as-an-agile-kanban-tool/","summary":"\u003cp\u003eAfter initially using Trello with ‘\u003ca href=\"http://scrumfortrello.com\" target=\"_blank\"\u003eScrum for Trello’\u003c/a\u003e\u0026rsquo; to run our companies Agile process and having to manually create burn downs and release estimates with Excel (\u003ca href=\"https://gist.github.com/chrismckelt/a8a7fb7cbf768e1423eb5da15070daa7\" target=\"_blank\"\u003eafter mangling data from the Trello API and a Google Spread sheet\u003c/a\u003e) we moved to Trello with GetCorrello (and switched to Kanban after a few months with the teams consent)\u003c/p\u003e\n\u003cp\u003eCharts from this tool are below.   The GetCorrello team were able to add features on demand. Would use them again!\u003c/p\u003e","title":"Trello with GetCorrello as an Agile Kanban Tool"},{"content":"Coursera Practical Machine Learning - Prediction Assignment Chris McKelt 17 September 2017 Introduction Executive summary Background Goal Data Obtaining Data Data Exploration Cleaning Data Training Model build - Random Forest Prediction - Random Forest Model build - Gradient Boosting Machine Prediction - Gradient Boosting Machine Introduction This is an analysis for final assignment of the Coursea course ‘Practical Machine Learning’.\nhttp://web.archive.org/web/20161224072740/http:/groupware.les.inf.puc-rio.br/har\nExecutive summary The gradient boosted machine (0.9998) achieved a better accuracy than the random forsest (0.9997)\nBackground Using devices such as Jawbone Up, Nike FuelBand, and Fitbit it is now possible to collect a large amount of data about personal activity relatively inexpensively. These type of devices are part of the quantified self movement - a group of enthusiasts who take measurements about themselves regularly to improve their health, to find patterns in their behavior, or because they are tech geeks. One thing that people regularly do is quantify how much of a particular activity they do, but they rarely quantify how well they do it. In this project, your goal will be to use data from accelerometers on the belt, forearm, arm, and dumbell of 6 participants. They were asked to perform barbell lifts correctly and incorrectly in 5 different ways. More information is available from the website here: http://groupware.les.inf.puc-rio.br/har (see the section on the Weight Lifting Exercise Dataset).\nThe exercises were performed by six male participants aged between 20-28 years, with little weight lifting experience.\nGoal Predict the manner in which a participant did the exercise (class A - properly - or any other incorrect way)\nData Obtaining Data The training data for this project are available here: https://d396qusza40orc.cloudfront.net/predmachlearn/pml-training.csv\nThe test data are available here: https://d396qusza40orc.cloudfront.net/predmachlearn/pml-testing.csv\nsave_file = function(url, name) { if (!file.exists(name)) { library(downloader) download(url, destfile = name) } } save_file(\u0026#34;https://d396qusza40orc.cloudfront.net/predmachlearn/pml-training.csv\u0026#34;, \u0026#34;pml-training.csv\u0026#34;) save_file(\u0026#34;https://d396qusza40orc.cloudfront.net/predmachlearn/pml-testing.csv\u0026#34;, \u0026#34;pml-testing.csv\u0026#34;) string40 \u0026lt;- \u0026#34;ncnnccnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\u0026#34; string80 \u0026lt;- \u0026#34;nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\u0026#34; string120 \u0026lt;- \u0026#34;nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\u0026#34; string160 \u0026lt;- \u0026#34;nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnc\u0026#34; colString \u0026lt;- paste(string40, string80, string120, string160, sep = \u0026#34;\u0026#34;) data.training \u0026lt;- readr::read_csv(\u0026#34;pml-training.csv\u0026#34;, col_names = TRUE, col_types = colString) data.testing \u0026lt;- readr::read_csv(\u0026#34;pml-testing.csv\u0026#34;, col_names = TRUE, col_types = colString) data.training \u0026lt;- as.data.frame(data.training) Data Exploration The goal of this project is to predict the manner in which they did the exercise. This is the “classe” variable in the training set, the last column. Let’s have a look at the training data. Both datasets have 160 rows with the rraining set having 160 observations and the testing having 20 observations.\ndim(data.training) ## [1] 19622 160 dim(data.testing) ## [1] 20 160 The ‘classe’ variable is the indicator of the training outcome. Classe ‘A’ corresponds to the specified execution of the exercise, while the other 4 classes correspond to common mistakes. Below shows a plot of the distribution of this variable throughout the training set. Cleaning Data To clean up the data we remove columns where ALL values are NA\ndata.training \u0026lt;- data.training[, colSums(is.na(data.training)) == 0] data.testing \u0026lt;- data.testing[, colSums(is.na(data.testing)) == 0] Training split the original training set because original test set does not have enough observations data.include \u0026lt;- createDataPartition(data.training$classe, p = .70, list = FALSE) data.train \u0026lt;- data.training[data.include,] data.test \u0026lt;- data.training[-data.include,] Model build - Random Forest For this random forest model, we apply cross validation: the data is being splitted into five parts, each of them taking the role of a validation set once. A model is built five times on the remaining data, and the classification error is computed on the validation set. The average of these five error rates is our final error. This can all be implemented using the caret train function. We set the seed as the sampling happens randomly.\ncat(\u0026#34;Random Forest model started\u0026#34;) ## Random Forest model started cluster \u0026lt;- makeCluster(detectCores() - 1) # convention to leave 1 core for OS registerDoParallel(cluster) fitControl.rf \u0026lt;- trainControl(method = \u0026#34;cv\u0026#34;, number = 5, allowParallel = TRUE) timer.start \u0026lt;- Sys.time() model.rf \u0026lt;- train(classe ~ ., data = data.train, method = \u0026#34;rf\u0026#34;, trControl = fitControl.rf, verbose = FALSE, na.action = na.omit) timer.end \u0026lt;- Sys.time() stopCluster(cluster) registerDoSEQ() paste(\u0026#34;Random Forest took: \u0026#34;, timer.end - timer.start, attr(timer.end - timer.start, \u0026#34;units\u0026#34;)) ## [1] \u0026#34;Random Forest took: 2.51922355095545 mins\u0026#34; Prediction - Random Forest prediction.rf \u0026lt;- predict(model.rf, data.test) confusion_matrix.rf \u0026lt;- confusionMatrix(prediction.rf, data.test$classe) confusion_matrix.rf ## Confusion Matrix and Statistics ## ## Reference ## Prediction A B C D E ## A 1673 0 0 0 0 ## B 1 1138 0 0 0 ## C 0 1 1026 0 0 ## D 0 0 0 964 0 ## E 0 0 0 0 1082 ## ## Overall Statistics ## ## Accuracy : 0.9997 ## 95% CI : (0.9988, 1) ## No Information Rate : 0.2845 ## P-Value [Acc \u0026gt; NIR] : \u0026lt; 2.2e-16 ## ## Kappa : 0.9996 ## Mcnemar\u0026#39;s Test P-Value : NA ## ## Statistics by Class: ## ## Class: A Class: B Class: C Class: D Class: E ## Sensitivity 0.9994 0.9991 1.0000 1.0000 1.0000 ## Specificity 1.0000 0.9998 0.9998 1.0000 1.0000 ## Pos Pred Value 1.0000 0.9991 0.9990 1.0000 1.0000 ## Neg Pred Value 0.9998 0.9998 1.0000 1.0000 1.0000 ## Prevalence 0.2845 0.1935 0.1743 0.1638 0.1839 ## Detection Rate 0.2843 0.1934 0.1743 0.1638 0.1839 ## Detection Prevalence 0.2843 0.1935 0.1745 0.1638 0.1839 ## Balanced Accuracy 0.9997 0.9995 0.9999 1.0000 1.0000 Model build - Gradient Boosting Machine Now we will do exactly the same, but use boosting instead of random forests. Getting the accuracy, predications… works with the same code.\ncat(\u0026#34;Gradient Boosting Machine model started\u0026#34;) ## Gradient Boosting Machine model started fitControl.gbm \u0026lt;- trainControl(method=\u0026#34;cv\u0026#34;,number=5,allowParallel=TRUE) timer.start \u0026lt;- Sys.time() model.gbm \u0026lt;- train(classe ~ ., data = data.train, method = \u0026#34;gbm\u0026#34;, trControl = fitControl.gbm, verbose = FALSE, na.action = na.omit) timer.end \u0026lt;- Sys.time() paste(\u0026#34;Gradient Boosting Machine took: \u0026#34;, timer.end - timer.start, attr(timer.end - timer.start, \u0026#34;units\u0026#34;)) ## [1] \u0026#34;Gradient Boosting Machine took: 3.89540884892146 mins\u0026#34; Prediction - Gradient Boosting Machine cat(\u0026#34;Gradient Boosting Machine predictions\u0026#34;) ## Gradient Boosting Machine predictions prediction.gbm \u0026lt;- predict(model.gbm, data.test) confusion_matrix.gbm \u0026lt;- confusionMatrix(prediction.gbm, data.test$classe) confusion_matrix.gbm ## Confusion Matrix and Statistics ## ## Reference ## Prediction A B C D E ## A 1673 0 0 0 0 ## B 1 1138 0 0 0 ## C 0 1 1026 0 0 ## D 0 0 0 964 0 ## E 0 0 0 0 1082 ## ## Overall Statistics ## ## Accuracy : 0.9997 ## 95% CI : (0.9988, 1) ## No Information Rate : 0.2845 ## P-Value [Acc \u0026gt; NIR] : \u0026lt; 2.2e-16 ## ## Kappa : 0.9996 ## Mcnemar\u0026#39;s Test P-Value : NA ## ## Statistics by Class: ## ## Class: A Class: B Class: C Class: D Class: E ## Sensitivity 0.9994 0.9991 1.0000 1.0000 1.0000 ## Specificity 1.0000 0.9998 0.9998 1.0000 1.0000 ## Pos Pred Value 1.0000 0.9991 0.9990 1.0000 1.0000 ## Neg Pred Value 0.9998 0.9998 1.0000 1.0000 1.0000 ## Prevalence 0.2845 0.1935 0.1743 0.1638 0.1839 ## Detection Rate 0.2843 0.1934 0.1743 0.1638 0.1839 ## Detection Prevalence 0.2843 0.1935 0.1745 0.1638 0.1839 ## Balanced Accuracy 0.9997 0.9995 0.9999 1.0000 1.0000 ","permalink":"https://blog.mckelt.com/articles/posts/coursera-practical-machine-learning-prediction-assignment/","summary":"\u003ch1 id=\"coursera-practical-machine-learning---prediction-assignment\"\u003eCoursera Practical Machine Learning - Prediction Assignment\u003c/h1\u003e\n\u003ch4 id=\"chris-mckelt\"\u003e\u003cem\u003eChris McKelt\u003c/em\u003e\u003c/h4\u003e\n\u003ch4 id=\"17-september-2017\"\u003e\u003cem\u003e17 September 2017\u003c/em\u003e\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#introduction\"\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#executive-summary\"\u003eExecutive summary\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#background\"\u003eBackground\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#goal\"\u003eGoal\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#data\"\u003eData\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#obtaining-data\"\u003eObtaining Data\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#data-exploration\"\u003eData Exploration\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#cleaning-data\"\u003eCleaning Data\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#training\"\u003eTraining\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#model-build---random-forest\"\u003eModel build - Random Forest\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#prediction---random-forest\"\u003ePrediction - Random Forest\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#model-build---gradient-boosting-machine\"\u003eModel build - Gradient Boosting Machine\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#prediction---gradient-boosting-machine\"\u003ePrediction - Gradient Boosting Machine\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"introduction\"\u003eIntroduction\u003c/h1\u003e\n\u003cp\u003eThis is an analysis for final assignment of the Coursea course ‘Practical Machine Learning’.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://web.archive.org/web/20161224072740/http:/groupware.les.inf.puc-rio.br/har\" target=\"_blank\"\u003ehttp://web.archive.org/web/20161224072740/http:/groupware.les.inf.puc-rio.br/har\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"executive-summary\"\u003eExecutive summary\u003c/h1\u003e\n\u003cp\u003eThe gradient boosted machine (0.9998) achieved a better accuracy than the random forsest (0.9997)\u003c/p\u003e","title":"Coursera Practical Machine Learning - Prediction Assignment"},{"content":"Format to run a small story mapping workshop\nElevator Pitch As a team work to decide on the elevator pitch ala\nFor [TARGET CUSTOMER TYPE] who want to [NEED DESIRE], [PRODUCT / FEATURE] is a [MARKET CATEGORY] that [KEY BENEFIT].\nDriver, Approver, Contributors, and Informed Identity key objects and people to deliver\nStory mapping Story Map Structure: Goals \u0026gt; Activities \u0026gt; Tasks \u0026gt; Stories\n","permalink":"https://blog.mckelt.com/articles/posts/story-mapping-workshop/","summary":"\u003cp\u003eFormat to run a small story mapping workshop\u003c/p\u003e\n\u003ch1 id=\"elevator-pitch\"\u003eElevator Pitch\u003c/h1\u003e\n\u003cp\u003eAs a team work to decide on the elevator pitch ala\u003c/p\u003e\n\u003cp\u003eFor [TARGET CUSTOMER TYPE] who want to [NEED  DESIRE], [PRODUCT / FEATURE] is a [MARKET CATEGORY] that [KEY BENEFIT].\u003c/p\u003e\n\u003ch1 id=\"driver-approver-contributors-and-informed\"\u003eDriver, Approver, Contributors, and Informed\u003c/h1\u003e\n\u003cp\u003eIdentity key objects and people to deliver\u003c/p\u003e\n\u003ch1 id=\"story-mapping\"\u003eStory mapping\u003c/h1\u003e\n\u003cp\u003eStory Map Structure: \u003cstrong\u003eGoals \u0026gt; Activities \u0026gt; Tasks \u0026gt; Stories\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120944692-73e75a00-c768-11eb-8121-3e9ddd34e8f4.png\"\u003e\u003c/p\u003e","title":"Story mapping workshop"},{"content":"This is an overview of how to build and debug a Dynamics 365 Field Services Mobile Application using Resco’s Woodford mobile framework (JavaScript library)\nPlease let me know if you have a better way to manage this development life cycle. Id be keen to improve the experience.\nWhat does the mobile application look like? The project solution on disk\nThis project uses TypeScript with VS Code. Typescript helped catch lots of issues before deployment.\nWhy TypeScript?\nRequirements to build and debug the solution Latest Typescript Visual Studio 2015 + LINQ Pad (just to copy the local dev files to the local Window Store Field Service App folder) Field Service – Dynamics 365 application installed How do I build the solution? Step 1 After setting up the files locally (mine are at c:\\dev\\vForms ) run the following commands in the root directory –\u0026gt; _npm install This should give you the TypeScript jQuery \u0026amp; Sizzle files for intellisense in VS Code / Visual Studio\nStep 2 To compile the TypeScript files to JavaScript (.ts –\u0026gt; .js) run the command \u0026ndash;\u0026gt; tsc –w (-w is watch mode so any saved change to a .TS file will trigger a compile)\nStep 3 Open up the file ‘vForms-directory-sync.linq’\nHere we need to replace the highlighted yellow with your local Field Service application data package directory\nRun this script and it will ‘watch’ your development files and copy them to the local Field Service application folder upon change.\nWarning: The Field Service application may occasional lock the file. And to refresh the view/execution of the files you need to exit the screen using them – then go back in (no Hot Module Replacement here I am afraid!)\nHow do I debug the solution? To help with debugging I have set a global Boolean variable DEBUG_ENABLED which optionally may be triggered remotely via the ‘msdyn_showtechnicalhelp’ field for a survey.\nThree steps are required to attach \u0026amp; debug the JavaScript/Typescript files\nStep 1 Follow the steps to setup your IE settings outlined here\nhttps://www.resco.net/debugging-offline-html-solution/\nStep 2 In your TypeScript/JavasScript file put the word ‘debugger’ to break out into a debug session\nStep 3 Attach Visual Studio to the MobileCrm.exe process\nVoila – you should be able to attach \u0026amp; debug the running JavaScript (note may take a few goes to warm up)\n","permalink":"https://blog.mckelt.com/articles/posts/dynamic-365-field-app-creating-a-resco/","summary":"\u003cp\u003eThis is an overview of how to build and debug a Dynamics 365 Field Services Mobile Application using \u003ca href=\"https://www.resco.net/woodford-overview/\" target=\"_blank\"\u003eResco’s Woodford\u003c/a\u003e mobile framework (JavaScript library)\u003c/p\u003e\n\u003cp\u003e\u003cem\u003ePlease let me know if you have a better way to manage this development life cycle. Id be keen to improve the experience.\u003c/em\u003e\u003c/p\u003e\n\u003ch1 id=\"what-does-the-mobile-application-look-like\"\u003eWhat does the mobile application look like?\u003c/h1\u003e\n\u003cp\u003eThe project solution on disk\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120943838-fa4d6d00-c763-11eb-9aeb-7607ff5b6027.png\"\u003e\u003c/p\u003e\n\u003cp\u003eThis project uses TypeScript with VS Code.   Typescript helped catch lots of issues before deployment.\u003c/p\u003e","title":"Dynamics 365 Field services mobile app debugging"},{"content":"PCA Principal Components Analysis (PCA) allows us to study and explore a set of quantitative variables measured on a set of objects\nCore Idea With PCA we seek to reduce the dimensionality (reduce the number of variables) of a data set while retaining as much as possible of the variation present in the data\nBefore performing a PCA(or any other multivariate method) we should start with some preliminary explorations\nDescriptive statistics Basic graphical displays Distribution of variables Pair-wise correlations among variables Perhaps transforming some variables ETC The minimal output from any PCA should contain 3 things:\nEigenvalues provide information about the amount of variability captured by each principal component\nScores or PCs (principal components) that provide coordinates to graphically represent objects in a lower dimensional space\nLoadings provide information to determine what variables characterize each principal component\nSome questions to keep in mind How many PCs should be retained? How good (or bad) is the data approximation with the retained PCs? What variables characterize each PC? Which variables are influential, and how are they correlated? Which variables are responsible for the patterns among objects? Are there any outlier objects? Links http://genomicsclass.github.io/book/pages/pca_svd.html\nhttp://www.r-bloggers.com/using-r-two-plots-of-principal-component-analysis/\nhttp://www.sthda.com/english/wiki/principal-component-analysis-in-r-prcomp-vs-princomp-r-software-and-data-mining\nhttp://stats.stackexchange.com/questions/143905/loadings-vs-eigenvectors-in-pca-when-to-use-one-or-another\nhttps://www.dropbox.com/s/mjdtdpgji74cut1/PCA_with_R.pdf?dl=0\nhttp://stats.stackexchange.com/questions/2691/making-sense-of-principal-component-analysis-eigenvectors-eigenvalues/35653#35653\n","permalink":"https://blog.mckelt.com/articles/posts/rdata-exploration/","summary":"\u003ch1 id=\"pca\"\u003ePCA\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003ePrincipal Components Analysis\u003c/strong\u003e (PCA) allows us to study and explore a set of quantitative variables measured on a set of objects\u003c/p\u003e\n\u003ch6 id=\"core-idea\"\u003eCore Idea\u003c/h6\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cp\u003eWith PCA we seek to reduce the dimensionality (reduce the number of variables) of a data set while retaining as much as possible of the variation present in the data\u003c/p\u003e\n\u003cp\u003eBefore performing a PCA(or any other multivariate method) we should start with some preliminary explorations\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eDescriptive statistics\u003c/li\u003e\n\u003cli\u003eBasic graphical displays\u003c/li\u003e\n\u003cli\u003eDistribution of variables\u003c/li\u003e\n\u003cli\u003ePair-wise correlations among variables\u003c/li\u003e\n\u003cli\u003ePerhaps transforming some variables\u003c/li\u003e\n\u003cli\u003eETC\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120943805-c6724780-c763-11eb-83bb-d1920d08269e.png\"\u003e\u003c/p\u003e","title":"R–Data Exploration"},{"content":"Import these references Sample script Graph ","permalink":"https://blog.mckelt.com/articles/posts/linqpad-and-f-scripts/","summary":"\u003ch1 id=\"import-these-references\"\u003eImport these references\u003c/h1\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120944745-b741c880-c768-11eb-9182-d53d9f451a72.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"sample-script\"\u003eSample script\u003c/h3\u003e\n\u003cscript src=\"https://gist.github.com/chrismckelt/7f2ec81a893e5f31d056.js\"\u003e\u003c/script\u003e\n\u003ch3 id=\"graph\"\u003eGraph\u003c/h3\u003e\n\u003cp\u003e \n\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120944762-c9bc0200-c768-11eb-8d84-3df4d099fe09.png\"\u003e\u003c/p\u003e","title":"LinqPad and F# Charting"},{"content":"Title Wholesale customers created with \u0026lsquo;on-hold\u0026rsquo; account status\nCard Description Wholesale customers created in D365 CE will initially have their account status placed \u0026lsquo;on hold\u0026rsquo; to disallow any credit transactions before they have their account credit checked and approved\nStory AS A finance manager I WANT new wholesale customers to begin with their account status 'oh hold' SO THAT no credit transactions are processed on their account until their account credit checked,approved and taken off hold. [Any supporting notes/diagrams]\nBackground any notes / emails / links for reference Acceptance Criteria Simple Acceptance Criteria new customer accounts created will have an on hold status accounts with on-hold status are not able to make purchases (without up front payment by credit card) customers on hold - scrap batteries can still be collected regression test suite 5, 39, 43 pass Specification by Example (for automated tests) Given a new wholesale customer is created in D365CE When that record is synced with D365FO Then the customer record status will be 'On Hold' Given a new wholesale customer is created in D365CE When a new purchase order is raised against the customer Then the request is denied due to the customer being on hold Given a new wholesale customer is taken off hold When a new purchase order is raised against the customer Then the request is accepted Further information https://www.mountaingoatsoftware.com/agile/user-stories\n","permalink":"https://blog.mckelt.com/articles/posts/user-story-example/","summary":"\u003ch1 id=\"title\"\u003eTitle\u003c/h1\u003e\n\u003cp\u003eWholesale customers created with \u0026lsquo;on-hold\u0026rsquo; account status\u003c/p\u003e\n\u003ch2 id=\"card-description\"\u003eCard Description\u003c/h2\u003e\n\u003cp\u003eWholesale customers created in D365 CE will initially have their account status placed \u0026lsquo;on hold\u0026rsquo; to disallow any credit transactions before they have their account credit checked and approved\u003c/p\u003e\n\u003ch4 id=\"story\"\u003eStory\u003c/h4\u003e\n\u003cpre\u003e\u003ccode\u003eAS A finance manager \nI WANT new wholesale customers to begin with their account status 'oh hold' \nSO THAT no credit transactions are processed on their account until their account credit checked,approved and taken off hold.\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cem\u003e[Any supporting notes/diagrams]\u003c/em\u003e\u003c/p\u003e","title":"User story example"},{"content":"1. Add the buildProvider config for razor inside the compilation element\n2. Application start –\u0026gt; Registers the html extension with razor\n3. Create a Start.cshtml page and ingest the index.html page\n\u0026lt;compilation debug\\=\u0026#34;true\u0026#34; targetFramework\\=\u0026#34;4.6\u0026#34; \\\u0026gt; \u0026lt;buildProviders\\\u0026gt; \u0026lt;add extension\\=\u0026#34;.html\u0026#34; type\\=\u0026#34;System.Web.WebPages.Razor.RazorBuildProvider\u0026#34;/\u0026gt; \u0026lt;/buildProviders\\\u0026gt; \u0026lt;/compilation\\\u0026gt; System.Web.Razor.RazorCodeLanguage.Languages.Add(\u0026#34;html\u0026#34;, new CSharpRazorCodeLanguage()); WebPageHttpHandler.RegisterExtension(\u0026#34;html\u0026#34;); @{ Layout \\= null; @RenderPage(\u0026#34;~/index.html\u0026#34;) } \u0026lt;!-- Version + @System.Reflection.Assembly.GetAssembly(typeof (Startup)).GetName().Version.ToString(); \\--\u0026gt; ","permalink":"https://blog.mckelt.com/articles/posts/map-html-extension-to-the-net-razor-view-engine/","summary":"\u003cp\u003e1. Add the \u003cem\u003ebuildProvider\u003c/em\u003e config for razor inside the compilation element\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//2015/09/image2.png\" target=\"_blank\"\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//image_thumb2.png\" title=\"image\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e2. Application start –\u0026gt; Registers the html extension with razor\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//2015/09/image1.png\" target=\"_blank\"\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//image_thumb1.png\" title=\"image\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e3. Create a Start.cshtml page and ingest the index.html page\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//2015/09/image3.png\" target=\"_blank\"\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//image_thumb3.png\" title=\"image\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;compilation debug\\=\u0026#34;true\u0026#34; targetFramework\\=\u0026#34;4.6\u0026#34; \\\u0026gt; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;buildProviders\\\u0026gt;     \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;add extension\\=\u0026#34;.html\u0026#34; type\\=\u0026#34;System.Web.WebPages.Razor.RazorBuildProvider\u0026#34;/\u0026gt;   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/buildProviders\\\u0026gt; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/compilation\\\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e System.Web.Razor.RazorCodeLanguage.Languages.Add(\u0026#34;html\u0026#34;, new CSharpRazorCodeLanguage()); WebPageHttpHandler.RegisterExtension(\u0026#34;html\u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@{ \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Layout \\= null;   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  @RenderPage(\u0026#34;~/index.html\u0026#34;) \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;!-- Version + @System.Reflection.Assembly.GetAssembly(typeof (Startup)).GetName().Version.ToString(); \\--\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Map .html extension to the .Net razor view engine"},{"content":"Write Value Tests Having drank the TDD cool aid over the years I went deep. BDD with Fitnesse, SpecFlow. Maximum code coverage %. Days fixing up UI tests. Ensuring this calls that – all code was covered.\nToday here is how I calculate a tests value.\nWill it help me discover a design? Is the functionality well known? (is this feature being tested to see if its used/needed) Will it stop hard to find bugs in the future? Is its value worth maintaining over time? Will the next person be able to understand and appreciate this test? If YES then write the test!\nFrom the Google SRE Book - dont \u0026lsquo;Automate Everything\u0026rsquo;, instead \u0026lsquo;Eliminate Toil\u0026rsquo; - where toil has some/all of these attributes.\nManual This includes work such as manually running a script that automates some task. Running a script may be quicker than manually executing each step in the script, but the hands-on time a human spends running that script (not the elapsed time) is still toil time.\nRepetitive If you’re performing a task for the first time ever, or even the second time, this work is not toil. Toil is work you do over and over. If you’re solving a novel problem or inventing a new solution, this work is not toil.\nAutomatable If a machine could accomplish the task just as well as a human, or the need for the task could be designed away, that task is toil. If human judgment is essential for the task, there’s a good chance it’s not toil.\nTactical Toil is interrupt-driven and reactive, rather than strategy-driven and proactive. Handling pager alerts is toil.We may never be able to eliminate this type of work completely, but we have to continually work toward minimizing it. No enduring value If your service remains in the same state after you have finished a task, the task was probably toil. If the task produced a permanent improvement in your service, it probably wasn’t toil, even if some amount of grunt work—such as digging into legacy code and configurations and straightening them out—was involved.\nO(n) with service growth If the work involved in a task scales up linearly with service size, traffic volume, or user count, that task is probably toil. An ideally managed and designed service can grow by at least one order of magnitude with zero additional work, other than some one-time efforts to add resources.\nref: https://landing.google.com/sre/book/chapters/eliminating-toil.html\n","permalink":"https://blog.mckelt.com/articles/posts/value-tests/","summary":"\u003ch2 id=\"write-value-tests\"\u003eWrite Value Tests\u003c/h2\u003e\n\u003cp\u003eHaving drank the TDD cool aid over the years I went deep.  BDD with Fitnesse, SpecFlow. Maximum code coverage %. Days fixing up UI tests. Ensuring this calls that – all code was covered.\u003c/p\u003e\n\u003cp\u003eToday here is how I calculate a tests value.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eWill it help me discover a design?\u003c/li\u003e\n\u003cli\u003eIs the functionality well known? (is this feature being tested to see if its used/needed)\u003c/li\u003e\n\u003cli\u003eWill it stop hard to find bugs in the future?\u003c/li\u003e\n\u003cli\u003eIs its value worth maintaining over time?\u003c/li\u003e\n\u003cli\u003eWill the next person be able to understand and appreciate this test?\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eIf YES then write the test!\u003c/p\u003e","title":"Value Tests --\u003e Eliminate Toil"},{"content":"Cloud Terms Firstly some terminology courtesy of Stackoverflow\nIAAS (Infrastructure As A Service) :\nThe base layer Deals with Virtual Machines, Storage (Hard Disks), Servers, Network, Load Balancers etc PAAS (Platform As A Service) :\nA layer on top of IAAS Runtimes (like .net/java runtimes), Databases (like MSSql, Oracle), Web Servers (IIS/tomcat etc) SAAS (Software As A Service) :\nA layer on top on PAAS Applications like email (Gmail, Yahoo mail etc), Social Networking sites (Facebook etc) IAAS AWS Azure Digital Ocean Google Cloud PAAS Azure DotCloud SalesForce OpenShift m-brace AppHarbour Heroku SAAS Azure AppHarbour Heroku SalesForce ","permalink":"https://blog.mckelt.com/articles/posts/choosing-a-cloud-platform-offering/","summary":"\u003ch2 id=\"cloud-terms\"\u003eCloud Terms\u003c/h2\u003e\n\u003cp\u003eFirstly some terminology courtesy of \u003ca href=\"http://stackoverflow.com/questions/16820336/what-is-saas-paas-and-iaas-with-examples\" target=\"_blank\"\u003eStackoverflow\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eIAAS (Infrastructure As A Service) :\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe base layer\u003c/li\u003e\n\u003cli\u003eDeals with Virtual Machines, Storage (Hard Disks), Servers, Network, Load Balancers etc\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003ePAAS (Platform As A Service) :\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eA layer on top of IAAS\u003c/li\u003e\n\u003cli\u003eRuntimes (like .net/java runtimes), Databases (like MSSql, Oracle), Web Servers (IIS/tomcat etc)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eSAAS (Software As A Service) :\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eA layer on top on PAAS\u003c/li\u003e\n\u003cli\u003eApplications like email (Gmail, Yahoo mail etc), Social Networking sites (Facebook etc)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"iaas\"\u003eIAAS\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"http://aws.amazon.com/\" target=\"_blank\"\u003eAWS\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://azure.microsoft.com/en-us/\" target=\"_blank\"\u003eAzure\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.digitalocean.com\" target=\"_blank\"\u003eDigital Ocean\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cloud.google.com/compute/\" target=\"_blank\"\u003eGoogle Cloud\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"paas\"\u003ePAAS\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"http://blogs.msdn.com/b/hanuk/archive/2013/12/03/which-windows-azure-cloud-architecture-paas-or-iaas.aspx\" target=\"_blank\"\u003eAzure\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.dotcloud.com/\" target=\"_blank\"\u003eDotCloud\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.salesforce.com/paas/\" target=\"_blank\"\u003eSalesForce\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.openshift.com/\" target=\"_blank\"\u003eOpenShift\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.m-brace.net/\" target=\"_blank\"\u003em-brace\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://appharbor.com\" target=\"_blank\"\u003eAppHarbour\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.heroku.com/\" target=\"_blank\"\u003eHeroku\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"saas\"\u003eSAAS\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"http://www.mexia.com.au/azure-app-service-the-new-cloud-integration-platform/\" target=\"_blank\"\u003eAzure\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://appharbor.com/page/how-it-works\" target=\"_blank\"\u003eAppHarbour\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.heroku.com/\" target=\"_blank\"\u003eHeroku\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.salesforce.com/saas/\" target=\"_blank\"\u003eSalesForce\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"Cloud Terms"},{"content":"https://gist.github.com/chrismckelt/3884f94078a7bd3a773b\n","permalink":"https://blog.mckelt.com/articles/posts/chocolatey-machine-setup/","summary":"\u003cp\u003e\u003ca href=\"https://gist.github.com/chrismckelt/3884f94078a7bd3a773b\" title=\"https://gist.github.com/chrismckelt/3884f94078a7bd3a773b\" target=\"_blank\"\u003ehttps://gist.github.com/chrismckelt/3884f94078a7bd3a773b\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e \u003cscript src=\"https://gist.github.com/chrismckelt/3884f94078a7bd3a773b.js\"\u003e\u003c/script\u003e\u003c/p\u003e","title":"Chocolatey machine setup"},{"content":"So after losing 6 months worth of posts I have now converted this blog to use WordPress.\nTo transfers the posts I wrote a simple linqpad script that uses WordPressSharp\nAfter trying Syntax highlighter I instead choose this code formatter.\n// need nuget WordPressSharp internal class FileStore { public IList\u0026lt;Post\u0026gt; Posts { get; private set; } public void ReadFiles() { const string folderPath = @\u0026#34;C:\\temp\\posts\u0026#34;; Posts = new List\u0026lt;Post\u0026gt;(); var files = Directory.GetFiles(folderPath); files.ToList().ForEach(ProcessFile); } private void ProcessFile(string filepath) { //Load xml XDocument xdoc = XDocument.Load(filepath); //Run query var posts = from lv1 in xdoc.Descendants(\u0026#34;post\u0026#34;) select new Post() { Title = lv1.Element(\u0026#34;title\u0026#34;).Value, Content = lv1.Element(\u0026#34;content\u0026#34;).Value, PublishDateTime = Convert.ToDateTime(lv1.Element(\u0026#34;pubDate\u0026#34;).Value), CustomFields = GetDesc(new KeyValuePair\u0026lt;string, string\u0026gt;(\u0026#34;Description\u0026#34;, lv1.Element(\u0026#34;description\u0026#34;).Value)) }; posts.ToList().ForEach(Posts.Add); } public CustomField[] GetDesc(params KeyValuePair\u0026lt;string,string\u0026gt;[] fieldsToAdd) { var list = new List\u0026lt;CustomField\u0026gt;(); foreach (var keyValuePair in fieldsToAdd) { list.Add(new CustomField() { Id=Guid.NewGuid().ToString(), Key=keyValuePair.Key, Value = keyValuePair.Value }); } return list.ToArray(); } } private static void Main(string[] args) { var url = \u0026#34;http://www.mckelt.com/blog/\u0026#34;; var cfg = new WordPressSiteConfig { BaseUrl = \u0026#34;/blog/xmlrpc.php\u0026#34;, BlogId = 1, Username = \u0026#34;username\u0026#34;, Password = \u0026#34;password\u0026#34; }; var fs = new FileStore(); fs.ReadFiles(); foreach (var post1 in fs.Posts.OrderBy(x=\u0026gt;x.PublishDateTime)) { post1.Status = \u0026#34;publish\u0026#34;; using (var client = new WordPressClient(cfg)) { client.NewPost(post1); } } } } ","permalink":"https://blog.mckelt.com/articles/posts/from-dotnetblogengine-to-wordpress/","summary":"\u003cp\u003eSo after losing 6 months worth of posts I have now converted this blog to use WordPress.\u003c/p\u003e\n\u003cp\u003eTo transfers the posts I wrote a simple \u003ca href=\"https://gist.github.com/chrismckelt/31a3c5ea9114f28f3170\" target=\"_blank\"\u003elinqpad\u003c/a\u003e script that uses \u003ca href=\"https://github.com/abrudtkuhl/WordPressSharp\" target=\"_blank\"\u003eWordPressSharp\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eAfter trying Syntax highlighter I instead choose this \u003ca href=\"https://code.google.com/p/codeformatterpluginforwindowslivewriter/downloads/detail?name=CodeFormatterPluginSetup2.5.1.msi\u0026amp;can=2\u0026amp;q=\" target=\"_blank\"\u003ecode formatter.\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// need nuget WordPressSharp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einternal \u003cspan style=\"color:#00a\"\u003eclass\u003c/span\u003e FileStore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   public IList\u0026lt;Post\u0026gt; Posts { get; private set; }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   public void ReadFiles()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       \u003cspan style=\"color:#00a\"\u003econst\u003c/span\u003e string folderPath = \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003e\u003cspan style=\"color:#a50\"\u003e\u0026#34;C:\u003c/span\u003e\u003cspan style=\"color:#a50\"\u003e\\t\u003c/span\u003e\u003cspan style=\"color:#a50\"\u003eemp\\posts\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       Posts =  new List\u0026lt;Post\u0026gt;();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e files = Directory.GetFiles(folderPath);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       files.ToList().ForEach(ProcessFile);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   private void ProcessFile(string filepath)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       //Load xml\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       XDocument xdoc = XDocument.Load(filepath);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       //Run query\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e posts = from lv1 \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e xdoc.Descendants(\u003cspan style=\"color:#a50\"\u003e\u0026#34;post\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                  select new Post()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                  {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                      Title = lv1.Element(\u003cspan style=\"color:#a50\"\u003e\u0026#34;title\u0026#34;\u003c/span\u003e).Value,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                      Content = lv1.Element(\u003cspan style=\"color:#a50\"\u003e\u0026#34;content\u0026#34;\u003c/span\u003e).Value,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                      PublishDateTime = Convert.ToDateTime(lv1.Element(\u003cspan style=\"color:#a50\"\u003e\u0026#34;pubDate\u0026#34;\u003c/span\u003e).Value),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                      CustomFields = GetDesc(new KeyValuePair\u0026lt;string, string\u0026gt;(\u003cspan style=\"color:#a50\"\u003e\u0026#34;Description\u0026#34;\u003c/span\u003e, lv1.Element(\u003cspan style=\"color:#a50\"\u003e\u0026#34;description\u0026#34;\u003c/span\u003e).Value))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                  };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      posts.ToList().ForEach(Posts.Add);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   public CustomField[] GetDesc(params KeyValuePair\u0026lt;string,string\u0026gt;[] fieldsToAdd)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e list = new List\u0026lt;CustomField\u0026gt;();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       foreach (\u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e keyValuePair \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e fieldsToAdd)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e           list.Add(new CustomField()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e           {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e               Id=Guid.NewGuid().ToString(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e               Key=keyValuePair.Key,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e               Value = keyValuePair.Value\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e           });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e list.ToArray();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   private \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e void Main(string[] args)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e url = \u003cspan style=\"color:#a50\"\u003e\u0026#34;http://www.mckelt.com/blog/\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e cfg = new WordPressSiteConfig\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                BaseUrl = \u003cspan style=\"color:#a50\"\u003e\u0026#34;/blog/xmlrpc.php\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                BlogId = \u003cspan style=\"color:#099\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Username = \u003cspan style=\"color:#a50\"\u003e\u0026#34;username\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Password = \u003cspan style=\"color:#a50\"\u003e\u0026#34;password\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e fs = new FileStore();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            fs.ReadFiles();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            foreach (\u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e post1 \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e fs.Posts.OrderBy(x=\u0026gt;x.PublishDateTime))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                post1.Status = \u003cspan style=\"color:#a50\"\u003e\u0026#34;publish\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                using (\u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e client = new WordPressClient(cfg))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    client.NewPost(post1);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"From DotNetBlogEngine to WordPress"},{"content":"Scrum to Kanban ","permalink":"https://blog.mckelt.com/articles/posts/scrum-to-kanban/","summary":"\u003ch1 id=\"scrum-to-kanban\"\u003eScrum to Kanban\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2020/08/Kanban-Process.gif\" target=\"_blank\"\u003e\u003cimg alt=\"Kanban Process\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images//Kanban-Process_thumb.gif\" title=\"Kanban Process\"\u003e\u003c/a\u003e\u003c/p\u003e","title":"Scrum to kanban"},{"content":"Source Control To track versions and manage an environment from deployment to recovery, source control is essential. Tracking changes, performing peer reviews before merging to the main master branch \u0026amp; the ability to rebuild/recover/revert to a previously known good state ensure quality throughout the process.\nExample source control : GitHub\nContinue Integration Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.\nBy integrating regularly, you can detect errors quickly, and locate them more easily.\nRunning new code through a pipeline of automated tests \u0026amp; peer review before reaching the test/uat environment ensures less regression errors \u0026amp; frustration for QA team.\nhttps://www.thoughtworks.com/continuous-integration\nExample CI : AppVeyor\nAutomated Tests (unit, integration, functional, acceptance, UI, subcutaneous) Test Driven Development (TDD) involves coding test cases checking the newly implemented scenarios function as required (and ensure no regression when changes occur)\nhttp://www.bas36.com/2012/07/benefits-of-test-driven-development/\nTDD is an essential tool in a programmers toolkit \u0026amp; is essential is required for modern dev positions.\n","permalink":"https://blog.mckelt.com/articles/posts/software-development-best-practice-minimum/","summary":"\u003ch1 id=\"source-control\"\u003eSource Control\u003c/h1\u003e\n\u003cp\u003eTo track versions and manage an environment from deployment to recovery, source control is essential.  Tracking changes, performing peer reviews before merging to the main master branch \u0026amp; the ability to rebuild/recover/revert to a previously known good state ensure quality throughout the process.\u003c/p\u003e\n\u003cp\u003eExample source control : \u003ca href=\"https://github.com/\" target=\"_blank\"\u003eGitHub\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"continue-integration\"\u003eContinue Integration\u003c/h1\u003e\n\u003cp\u003eContinuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.\u003c/p\u003e","title":"Software Development Best Practice (minimum)"},{"content":"[TestFixture] public class RouteTestFixture { [Test] public void Routes _should _not _change() { const string good = @ \u0026#34;all existing routes go here (hint run the test first then copy output to here)\u0026#34;; var goodRoutes = good.Split(Convert.ToChar(\u0026#34;;\u0026#34;)); var notFound = new List \u0026lt; string \u0026gt; (); var ass = Assembly.GetAssembly(typeof (EventStatisticsController)); var sb = new StringBuilder(); foreach(var type in ass.GetTypes()) { try { var members = type.GetMembers(); for (int i = 0; i \u0026lt; members.Length; i++) { if (members[i].IsDefined(typeof (RouteAttribute), false)) { Object[] atts = members[i].GetCustomAttributes(typeof (RouteAttribute), false); for (int j = 0; j \u0026lt; atts.Length; j++) { var routeAttribute = (RouteAttribute) atts[j]; string route = routeAttribute.Template + @ \u0026#34;/\u0026#34; + routeAttribute.Name; Console.WriteLine(route); sb.Append(route + \u0026#34;;\u0026#34;); if (!goodRoutes.Contains(route)) { notFound.Add(route); } } } } } catch (Exception e) { Console.WriteLine(@ \u0026#34;An exception occurred: {0}\u0026#34;, e.Message); } } if (notFound.Any()) { Console.WriteLine(@ \u0026#34;-- MISSING ROUTES --\u0026#34;); foreach(var nf in notFound) { Console.WriteLine(nf); } Assert.Fail(\u0026#34;Missing Routes: \u0026#34; + notFound.Count); } else { Assert.True(true, \u0026#34;All routes matched\u0026#34;); } Console.WriteLine(@ \u0026#34;------------------------------------------------\u0026#34;); Console.WriteLine(@ \u0026#34;Match the following string for future tests\u0026#34;); Console.WriteLine(sb.ToString()); } } ","permalink":"https://blog.mckelt.com/articles/posts/web-api-test-to-ensure-public-routes-do-not-change-3-2-2-2/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[TestFixture] \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epublic \u003cspan style=\"color:#00a\"\u003eclass\u003c/span\u003e RouteTestFixture {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  [Test]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  public void Routes _should _not _change() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#00a\"\u003econst\u003c/span\u003e string good = \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#34;all existing routes go here (hint run the test first then copy output to here)\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e goodRoutes = good.Split(Convert.ToChar(\u003cspan style=\"color:#a50\"\u003e\u0026#34;;\u0026#34;\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e notFound = new List \u0026lt; string \u0026gt; ();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e ass = Assembly.GetAssembly(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (EventStatisticsController));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e sb = new StringBuilder();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    foreach(\u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e type \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e ass.GetTypes()) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      try {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e members = type.GetMembers();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#00a\"\u003efor\u003c/span\u003e (int i = \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e; i \u0026lt; members.Length; i++) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (members[i].IsDefined(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (RouteAttribute), \u003cspan style=\"color:#0aa\"\u003efalse\u003c/span\u003e)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Object[] atts = members[i].GetCustomAttributes(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (RouteAttribute), \u003cspan style=\"color:#0aa\"\u003efalse\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003efor\u003c/span\u003e (int j = \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e; j \u0026lt; atts.Length; j++) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e routeAttribute = (RouteAttribute) atts[j];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              string route = routeAttribute.Template + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e + routeAttribute.Name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              Console.WriteLine(route);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              sb.Append(route + \u003cspan style=\"color:#a50\"\u003e\u0026#34;;\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (!goodRoutes.Contains(route)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                notFound.Add(route);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      } catch (Exception e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Console.WriteLine(\u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#34;An exception occurred: {0}\u0026#34;\u003c/span\u003e, e.Message);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (notFound.Any()) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      Console.WriteLine(\u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#34;-- MISSING ROUTES --\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      foreach(\u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e nf \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e notFound) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Console.WriteLine(nf);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      Assert.Fail(\u003cspan style=\"color:#a50\"\u003e\u0026#34;Missing Routes: \u0026#34;\u003c/span\u003e + notFound.Count);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    } \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      Assert.True(\u003cspan style=\"color:#0aa\"\u003etrue\u003c/span\u003e, \u003cspan style=\"color:#a50\"\u003e\u0026#34;All routes matched\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Console.WriteLine(\u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#34;------------------------------------------------\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Console.WriteLine(\u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#34;Match the following string for future tests\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Console.WriteLine(sb.ToString());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Web API Test to ensure public routes do not change"},{"content":"Principles we follow Numero Uno Our primary principle is to work as a team to deliver the best outcomes for the business.\nTransparency We combine face to face and verbal communcation with individual focus and use tools such as Slack, Trello, and GitHub to communicate openly within a project, within our team, and publicly.\nHonesty While we are considerate of people\u0026rsquo;s feelings and opinions, we cannot let those concerns get in the way of getting the right outcome for the business and the success of our work. We\u0026rsquo;d rather be too honest than too polite.\nTrust Our standards are very high, and bringing on a new team member requires a \u0026ldquo;yes\u0026rdquo; from everyone who participated in the interview process. Therefore, we expect the best from each other, give each other the benefit of the doubt, and encourage each other to take initiative to improve ourselves to improve my contribution to the team and the company.\nContinuous Improvement We recognize that we can always be better. Therefore, we have strong opinions, loosely held, and take initiative to improve ourselves, the company, and our community. We are proponents of the Agile manifesto\nTime We work at a sustainable pace. We work four days for the business and one day on \u0026ldquo;investment time.\u0026rdquo; We typically spend Monday-Thursday on business work and Friday on investment.\nWe believe in working wherever and whenever we work best. Because we rely on each other we confirm if we cannot meet a commitment, including letting our team members know if we cannot get to the office.\nWe know face to face communcation with our team is paramount \u0026amp; commit to spending at least 3 days in the office per week for conversation.\nWhen taking time off during work, we discuss how it will impact the schedule with other team members.\nWe communicate when and where we work to our team through Slack.\nInvestment Investment time is time for investment in ourselves, our company, and our community. Primarily this means doing something that interests us like building tools for our team, contributing to open source, researching \u0026amp; presenting on a topic, attending community events, or just improving the workplace zen. The goal is to encourage individuals to improve and share their knowledge with the rest of the team.\nWe organize our investment work on the \u0026ldquo;Team Time\u0026rdquo; Trello board.\nPlanning together One of our primary process goals is to make frequent, small releases of our working software.\nThis section describes how we achieve one week\u0026rsquo;s worth of iteration on a product. It lays out the process we follow and some communication tactics.\nAgile Standups Being a virtual team we use tatsu.io to do our onlines \u0026lsquo;standups\u0026rsquo;\nWe mention what we are doing. And how we can make things more awesome.\nWe do this in order to:\nCommunicate what we are doing Learn what others are doing so you can help them. Build accountability and trust. Work hours We try to have 4-6 hours in the work day that overlap for synchronous communication.\nFor some people, it is sometimes difficult to disengage from work when working at home. Also, flexible hours means that sometime one may work non-traditional hours in the day. We should be conscious to keep to a sustainable pace and take a break away from work.\nMeasuring for improvement What gets measured gets done\nWe measure ourselves using the following metrics\nOn-Time Delivery Product Quality Customer/User Satisfaction Business Value Developing with standards Code Reviews Here\u0026rsquo;s the flow. Read our git protocol for the git commands.\nCreate a local feature branch based off master. When feature is complete and tests pass, stage the changes. When you\u0026rsquo;ve staged the changes, commit them. Write a good commit message. Share your branch. Submit a GitHub pull request. Ask for a code review in Slack. A team member other than the author reviews the pull request. They follow Code Review guidelines to avoid miscommunication. They make comments and ask questions directly on lines of code in the GitHub web interface or in Slack. When satisfied, they comment on the pull request \u0026ldquo;Ready to merge.\u0026rdquo; Rebase interactively. Squash commits like \u0026ldquo;Fix whitespace\u0026rdquo; into one or a small number of valuable commit(s). Edit commit messages to reveal intent. View a list of new commits. View changed files. Merge branch into master. Delete your remote feature branch. Delete your local feature branch. Test-Driven Development moves code failure earlier in the development process. It\u0026rsquo;s better to have a failing test on your development machine than in production. It also allows you to have tighter feedback cycles.\nCode reviews that happen right before code goes into master offer similar benefits:\nThe whole team learns about new code as it is written. Mistakes are caught earlier. Coding standards are more likely to be established, discussed, and followed. Feedback from this style of code review is far more likely to be applied. No one forgets context (\u0026ldquo;Why did we write this?\u0026rdquo;) since it\u0026rsquo;s fresh in the author\u0026rsquo;s mind. Continuous Integration Martin Fowler has an extensive description of Continuous Integration. The basics are:\nWe have a test suite that each developer runs on their own machine. When they commit their code to a shared version control repository, the tests are run again, \u0026ldquo;integrated\u0026rdquo; with code from other developers. This helps ensure there\u0026rsquo;s nothing specific to the developer\u0026rsquo;s machine making the tests pass. The code in version control needs to run cleanly in production later so before the code is allowed to be deployed to production, it is run on a CI server or service.\nWhen a build fails, we get alerts in Slack and via email. Click the alert and we see a backtrace that gives us a hint of how to \u0026ldquo;fix the build.\u0026rdquo;\nWhen we write the fix and commit to version control again, we\u0026rsquo;ll get a \u0026ldquo;passing build\u0026rdquo; alert in Slack and via email. Click the alert and we see the passing build.\nGreen is good.\nA solid test suite is an absolute requirement for a web application in our opinion. However, one major problem with test suites is that they get slow as they get large.\nCI can ease the pain by distributing the test runs in parallel. We\u0026rsquo;ve had 45 minute test suites cut down to 2 minutes using this technique.\nWe\u0026rsquo;ve used CruiseControl, Team City, TFS and other CI platforms/libraries that we manage ourselves. This resulted in many hours of expensive attention.\nWe use AppVeyor\nCI test runs are triggered by GitHub post-receive hooks. The hooks we have on most of our GitHub repos are:\nProduction We live in a magical modern era where many problems have already been solved for us. We focus on the core product as much as possible and outsource operations as much as possible to external services.\nThis saves time and money. We can get started using those services in minutes, and pay a service tens or hundreds of dollars per month instead of paying developers thousands or tens of thousands.\n","permalink":"https://blog.mckelt.com/articles/posts/code-test-3-2-2/","summary":"\u003ch2 id=\"principleswe-follow\"\u003ePrinciples we follow\u003c/h2\u003e\n\u003ch3 id=\"numero-uno\"\u003eNumero Uno\u003c/h3\u003e\n\u003cp\u003eOur primary principle is to work as a team to deliver the best outcomes for the business.\u003c/p\u003e\n\u003ch3 id=\"transparency\"\u003eTransparency\u003c/h3\u003e\n\u003cp\u003eWe combine face to face and verbal communcation with individual focus and use tools such as Slack, Trello, and GitHub to communicate openly within a project, within our team, and publicly.\u003c/p\u003e\n\u003ch3 id=\"honesty\"\u003eHonesty\u003c/h3\u003e\n\u003cp\u003eWhile we are considerate of people\u0026rsquo;s feelings and opinions, we cannot let those concerns get in the way of getting the right outcome for the business and the success of our work. We\u0026rsquo;d rather be too honest than too polite.\u003c/p\u003e","title":"Software Playbook"},{"content":"Code \u0026ndash;\u0026gt; https://github.com/chrismckelt/XUnit.OptionallyIgnore\nNuGet \u0026ndash;\u0026gt; https://www.nuget.org/packages/Xunit.SpecFlow.AssertSkip/\nAs Xunit has no Assert.Ignore() using the OptionallyIgnoreTestFactAttribute attribute on a method and setting McKeltCustom.SpecflowPlugin.Settings.IgnoreLocally == true will ignore the test at runtime\nIn SpecFlow set this as a plugin and use the tag @IgnoreLocally\u0026ndash; before each test scenario is run turn on/off the setting to run this test.\nSample usage:\nnamespace Tester { public class Dummy { public Dummy() { McKeltCustom.SpecflowPlugin.Settings.IgnoreLocally = true; } } public class TestFixture : IUseFixture\u0026lt;Dummy\u0026gt; { [OptionallyIgnoreTestFact\\] public void DoesThisWork() { Assert.True(false, \u0026#34;This should not be run\u0026#34;); } public void SetFixture(Dummy data) { throw new NotImplementedException(); } } } SpecFlow tag can be on a feature or a scenario\nAdd the following to the .config file\n\u0026lt;specFlow\u0026gt; \u0026lt;!--\u0026lt;unitTestProvider name=\u0026quot;xUnit\u0026quot; /\u0026gt;--\u0026gt; \u0026lt;generator allowDebugGeneratedFiles=\u0026quot;false\u0026quot; allowRowTests=\u0026quot;true\u0026quot; generateAsyncTests=\u0026quot;false\u0026quot; path=\u0026quot;.\\lib\u0026quot;/\u0026gt; \u0026lt;runtime stopAtFirstError=\u0026quot;false\u0026quot; missingOrPendingStepsOutcome=\u0026quot;Ignore\u0026quot;\u0026gt; \u0026lt;!--\u0026lt;dependencies\u0026gt; \u0026lt;register name=\u0026quot;CustomGeneratorPlugin\u0026quot; type=\u0026quot;PhoenixCustom.Generator.SpecflowPlugin.CustomGeneratorPlugin, PhoenixCustom.Generator.SpecflowPlugin\u0026quot; as=\u0026quot;PhoenixCustom.Generator.SpecflowPlugin.CustomGeneratorPlugin, PhoenixCustom.Generator.SpecflowPlugin\u0026quot; /\u0026gt; \u0026lt;register name=\u0026quot;CustomGeneratorProvider\u0026quot; type=\u0026quot;PhoenixCustom.Generator.SpecflowPlugin.CustomGeneratorProvider, PhoenixCustom.Generator.SpecflowPlugin\u0026quot; as=\u0026quot;PhoenixCustom.Generator.SpecflowPlugin.CustomGeneratorProvider, PhoenixCustom.Generator.SpecflowPlugin\u0026quot; /\u0026gt; \u0026lt;/dependencies\u0026gt;--\u0026gt; \u0026lt;/runtime\u0026gt; \u0026lt;trace traceSuccessfulSteps=\u0026quot;true\u0026quot; traceTimings=\u0026quot;false\u0026quot; minTracedDuration=\u0026quot;0:0:0.1\u0026quot; stepDefinitionSkeletonStyle=\u0026quot;RegexAttribute\u0026quot;/\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;add name=\u0026quot;McKeltCustom\u0026quot; path=\u0026quot;.\\lib\u0026quot; type=\u0026quot;GeneratorAndRuntime\u0026quot;/\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config --\u0026gt; \u0026lt;stepAssemblies\u0026gt; \u0026lt;!-- This attribute is required in order to use StepArgument Transformation as described here; https://github.com/marcushammarberg/SpecFlow.Assist.Dynamic/wiki/Step-argument-transformations --\u0026gt; \u0026lt;!-- This attribute is required in order to use StepArgument Transformation as described here; https://github.com/marcusoftnet/SpecFlow.Assist.Dynamic/wiki/Step-argument-transformations --\u0026gt; \u0026lt;stepAssembly assembly=\u0026quot;SpecFlow.Assist.Dynamic\u0026quot;/\u0026gt; \u0026lt;/stepAssemblies\u0026gt; \u0026lt;/specFlow\u0026gt; Finally put the all compiled assemblies into a lib folder in the root folder of your SpecFlow project\nTests marked with @IgnoreLocally or OptionallyIgnoreTest will now skip the test if McKeltCustom.SpecflowPlugin.Settings.IgnoreLocally = true\n","permalink":"https://blog.mckelt.com/articles/posts/xunit-ignore-test-at-runtime-with-specflow-tag-ignorelocally-2-2/","summary":"\u003cp\u003eCode \u0026ndash;\u0026gt; \u003ca href=\"https://github.com/chrismckelt/XUnit.OptionallyIgnore\" target=\"_blank\"\u003ehttps://github.com/chrismckelt/XUnit.OptionallyIgnore\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eNuGet \u0026ndash;\u0026gt; \u003ca href=\"https://www.nuget.org/packages/Xunit.SpecFlow.AssertSkip/\" target=\"_blank\"\u003ehttps://www.nuget.org/packages/Xunit.SpecFlow.AssertSkip/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eAs Xunit has no Assert.Ignore() using the OptionallyIgnoreTestFactAttribute attribute on a method and setting McKeltCustom.SpecflowPlugin.Settings.IgnoreLocally == true will ignore the test at runtime\u003c/p\u003e\n\u003cp\u003eIn SpecFlow set this as a plugin and use the tag \u003cstrong\u003e@IgnoreLocally\u003c/strong\u003e\u0026ndash; before each test scenario is run turn on/off the setting to run this test.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSample usage:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enamespace Tester\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    public class Dummy\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public Dummy()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            McKeltCustom.SpecflowPlugin.Settings.IgnoreLocally = true;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    public class TestFixture : IUseFixture\u0026lt;Dummy\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        [OptionallyIgnoreTestFact\\]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public void DoesThisWork()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Assert.True(false, \u0026#34;This should not be run\u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public void SetFixture(Dummy data)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            throw new NotImplementedException();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eSpecFlow tag can be on a feature or a scenario\u003c/p\u003e","title":"XUnit Ignore test at runtime (with SpecFlow tag @IgnoreLocally)"},{"content":"The software design process Why Waterfall fails •Waterfall projects have 3x the failure rate (29% vs. 9%) and 1/3 the success rate (14% vs. 42%) of Agile projects (Standish Group, CHAOS Report 2012)\n•Inventor of Waterfall Winston W. Royce described in his academic paper written in 1970 that it was \u0026ldquo;risky and invites failure\u0026rdquo; and went on to describe Incremental development.\n•Recent failed waterfall projects that scrapped\n•UK Govt. £12 Billion for national program for NHS IT\n•US Air Force - 6 year project with cost of $1.3 Billion\n•QLD Health $1.2 Billion\nAgile vs. Waterfall Agile techniques deliver business-critical solutions at 40% lower cost, 50% faster and with significantly greater fit and quality.\nSource - © Standish Group CHAOS report 1994 – 2010. Sample size over 40,000 completed IT Projects.\nWhy Change? History has proven that those businesses that do adapt die.\nKodak failed to embrace digital cameras\nHow will Agile help us? •Reduce time to market\n•Reduce risk by finding errors earlier in the process\n•Early access to the software during the life cycle\n•Greater flexibility to change\n•Early cancellation(or failure) hurts less\n•Reduced defect count\n•Maintain compliance levels and auditory requirements\n•Improved ROI\n•Improved transparency for stake holders/management\n","permalink":"https://blog.mckelt.com/articles/posts/why-agile/","summary":"\u003ch2 id=\"the-software-design-process\"\u003eThe software design process\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120944174-a8a5e200-c765-11eb-8b0e-f12278a98cb0.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"why-waterfall-fails\"\u003eWhy Waterfall fails\u003c/h2\u003e\n\u003cp\u003e•Waterfall projects have 3x the failure rate (29% vs. 9%) and 1/3 the success rate (14% vs. 42%) of Agile projects (Standish Group, CHAOS Report 2012)\u003c/p\u003e\n\u003cp\u003e•Inventor of Waterfall \u003ca href=\"http://pascal.gugenberger.net/thoughts/waterfall-accident.html\" target=\"_blank\"\u003eWinston W. Royce\u003c/a\u003e described in his academic paper written in 1970 that it was \u0026ldquo;risky and invites failure\u0026rdquo; and went on to describe Incremental development.\u003c/p\u003e\n\u003cp\u003e•Recent failed waterfall projects that scrapped\u003c/p\u003e\n\u003cp\u003e•UK Govt. \u003ca href=\"http://www.dailymail.co.uk/news/article-2040259/NHS-IT-project-failure-Labours-12bn-scheme-scrapped.html\" target=\"_blank\"\u003e£12 Billion\u003c/a\u003e for national program for NHS IT\u003c/p\u003e","title":"Why Agile?"},{"content":"`\nFSharp Canopy Tests namespace RegressionTests open System open System.Configuration open runner open canopy open configuration open reporters open QuoteHelper module QuoteSiteTests = let runTest = ( start chrome let mainBrowser = browser elementTimeout \u0026lt;- 15.0 compareTimeout \u0026lt;- 15.0 let _testpage = ConfigurationManager.AppSettings.\\[\u0026#34;AolSiteUrl\u0026#34;] let _username = ConfigurationManager.AppSettings.\\[\u0026#34;AolChallengerId\u0026#34;] let _password = ConfigurationManager.AppSettings.\\[\u0026#34;AolPassword\u0026#34;] let _passwordChangeToThis = ConfigurationManager.AppSettings.\\[\u0026#34;AolPasswordChangeToThis\u0026#34;] let _includePasswordChangeTest = ConfigurationManager.AppSettings.\\[\u0026#34;IncludePasswordChangeTest\u0026#34;] let _quickSearchText = ConfigurationManager.AppSettings.\\[\u0026#34;QuickSearchText\u0026#34;] let _quickSearchFindInvestor = ConfigurationManager.AppSettings.\\[\u0026#34;QuickSearchFindInvestor\u0026#34;] let _path = ConfigurationManager.AppSettings.\\[\u0026#34;OutputTestResults\u0026#34;] QuoteHelper.deleteFiles _path \u0026#34;\u0026#34; true for file in System.IO.Directory.EnumerateFiles(_path) do let tempPath = System.IO.Path.Combine(_path, file) System.IO.File.Delete(tempPath) context (\u0026#34;Testing :: eQuote - \u0026#34; + _testpage + \u0026#34;/Quote\u0026#34;) before (fun _ -\u0026gt; describe \u0026#34;Starting test\u0026#34; url (_testpage + \u0026#34;/Quote\u0026#34;) ) ntest \u0026#34;Login\u0026#34; (fun _ -\u0026gt; describe (\u0026#34;Login with \u0026#34; + _username) url _testpage \u0026#34;#userId\u0026#34; \u0026lt;\u0026lt; _username \u0026#34;#password\u0026#34; \u0026lt;\u0026lt; _password click \u0026#34;.submit\u0026#34; // on (_testpage + \u0026#34;/Secure/Home/\u0026#34;) ) ntest \u0026#34;GIP Quote - Fixed Term\u0026#34; (fun _ -\u0026gt; describe \u0026#34;Creating GIP quote – fixed 3 year\u0026#34; js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]:first\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnContinue1\u0026#34; sleep 5 let setQuote = QuoteHelper.createQuoteTerm \u0026#34;100000\u0026#34; \u0026#34;Monthly\u0026#34; \u0026#34;3\u0026#34; js setQuote |\u0026gt; ignore click \u0026#34;#btnRunQuote\u0026#34; sleep 5 click \u0026#34;#btnSaveQuote\u0026#34; sleep 3 let linkText = read \u0026#34;#yourQuoteId\u0026#34; describe linkText screenshot _path linkText |\u0026gt; ignore ) ntest \u0026#34;GIP quote – life\u0026#34; (fun _ -\u0026gt; describe \u0026#34;Creating GIP quote – life\u0026#34; js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]::nth(1)\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnContinue1\u0026#34; sleep 5 js \u0026#34; $(\u0026#39;input:radio\\[name=ProductTerm]::nth(1)\u0026#39;).click();\u0026#34; |\u0026gt; ignore sleep 1 let setQuote = QuoteHelper.createQuoteLife \u0026#34;100000\u0026#34; \u0026#34;Monthly\u0026#34; js setQuote |\u0026gt; ignore sleep 1 js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnRunQuote\u0026#34; sleep 5 click \u0026#34;#btnSaveQuote\u0026#34; sleep 3 let linkText = read \u0026#34;#yourQuoteId\u0026#34; describe linkText screenshot _path linkText |\u0026gt; ignore ) ntest \u0026#34;GA Quote - Fixed Term\u0026#34; (fun _ -\u0026gt; describe \u0026#34;Creating Fee for service annuity quote - FIXED\u0026#34; js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]:first\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnContinue1\u0026#34; sleep 5 let setQuote = QuoteHelper.createQuoteTerm \u0026#34;100000\u0026#34; \u0026#34;Monthly\u0026#34; \u0026#34;3\u0026#34; js setQuote |\u0026gt; ignore sleep 1 js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0.0055\u0026#39;);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnRunQuote\u0026#34; sleep 5 click \u0026#34;#btnSaveQuote\u0026#34; sleep 3 let linkText = read \u0026#34;#yourQuoteId\u0026#34; describe linkText screenshot _path linkText |\u0026gt; ignore ) ntest \u0026#34;GA quote – life\u0026#34; (fun _ -\u0026gt; describe \u0026#34;Creating GA quote – life\u0026#34; js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]::nth(1)\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnContinue1\u0026#34; sleep 5 js \u0026#34; $(\u0026#39;input:radio\\[name=ProductTerm]::nth(1)\u0026#39;).click();\u0026#34; |\u0026gt; ignore sleep 1 let setQuote = QuoteHelper.createQuoteLife \u0026#34;100000\u0026#34; \u0026#34;Yearly\u0026#34; js setQuote |\u0026gt; ignore sleep 1 js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnRunQuote\u0026#34; sleep 5 click \u0026#34;#btnSaveQuote\u0026#34; sleep 3 let linkText = read \u0026#34;#yourQuoteId\u0026#34; describe linkText screenshot _path linkText |\u0026gt; ignore ) ntest \u0026#34;GreenId Test\u0026#34; (fun _ -\u0026gt; describe \u0026#34;GreenId Test\u0026#34; js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]::nth(1)\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnContinue1\u0026#34; sleep 5 js \u0026#34; $(\u0026#39;input:radio\\[name=ProductTerm]::nth(1)\u0026#39;).click();\u0026#34; |\u0026gt; ignore sleep 1 let setQuote = QuoteHelper.createQuoteLife \u0026#34;100000\u0026#34; \u0026#34;Yearly\u0026#34; js setQuote |\u0026gt; ignore sleep 1 js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;);\u0026#34; |\u0026gt; ignore click \u0026#34;#btnRunQuote\u0026#34; sleep 5 click \u0026#34;#btnSaveQuote\u0026#34; sleep 3 let linkText = read \u0026#34;#yourQuoteId\u0026#34; describe linkText click \u0026#34;#btnApply\u0026#34; sleep 5 js QuoteHelper.greenId |\u0026gt; ignore sleep 1 click \u0026#34;#InvestorDetails_IdentityVerification_CheckId\u0026#34; screenshot _path (\u0026#34;GreenId -\u0026#34; + linkText )|\u0026gt; ignore ) run () quit mainBrowser ) namespace RegressionTests module QuoteHelper = let createQuoteTerm amount paymentFrequency term = ( @\u0026#34; $(\u0026#39;#InvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;); $(\u0026#39;#InvestorDetails_GivenNames\u0026#39;).val(\u0026#39;test\u0026#39;); $(\u0026#39;#InvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;); $(\u0026#39;#InvestorDetails_DateOfBirth_day\u0026#39;).val(1); $(\u0026#39;#InvestorDetails_DateOfBirth_month\u0026#39;).val(1); $(\u0026#39;#InvestorDetails_DateOfBirth_year\u0026#39;).val(1937); $(\u0026#39;#InvestmentAmount\u0026#39;).val(\u0026#34; + amount + \u0026#34;); $(\u0026#39;#InvestmentAmount_editor\u0026#39;).val(\u0026#39;$100,000.00\u0026#39;); $(\u0026#39;#PaymentFrequency\u0026#39;).val(\u0026#39;\u0026#34; + paymentFrequency + \u0026#34;\u0026#39;); $(\u0026#39;#Term\u0026#39;).val(\u0026#39;\u0026#34; + term + \u0026#34;\u0026#39;); $(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;); $(\u0026#39;#Indexation\u0026#39;).val(\u0026#39;ZeroPercent\u0026#39;); $(\u0026#39;#OngoingCommissionRate\u0026#39;).val(\u0026#39;0.00550\u0026#39;); $(\u0026#39;#ResidualCapitalValueRate\u0026#39;).val(\u0026#39;1.00000\u0026#39;); $(\u0026#39;#JointInvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;); $(\u0026#39;#JointInvestorDetails_GivenNames\u0026#39;).val(\u0026#39;joint test\u0026#39;); $(\u0026#39;#JointInvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;); $(\u0026#39;#JointInvestorDetails_DateOfBirth_day\u0026#39;).val(31); $(\u0026#39;#JointInvestorDetails_DateOfBirth_month\u0026#39;).val(12); $(\u0026#39;#JointInvestorDetails_DateOfBirth_year\u0026#39;).val(1956);\u0026#34;) let createQuoteLife amount paymentFrequency = ( @\u0026#34; $(\u0026#39;#InvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;); $(\u0026#39;#InvestorDetails_GivenNames\u0026#39;).val(\u0026#39;test\u0026#39;); $(\u0026#39;#InvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;); $(\u0026#39;#InvestorDetails_DateOfBirth_day\u0026#39;).val(1); $(\u0026#39;#InvestorDetails_DateOfBirth_month\u0026#39;).val(1); $(\u0026#39;#InvestorDetails_DateOfBirth_year\u0026#39;).val(1937); $(\u0026#39;#InvestmentAmount\u0026#39;).val(\u0026#34; + amount + \u0026#34;); $(\u0026#39;#InvestmentAmount_editor\u0026#39;).val(\u0026#39;$100,000.00\u0026#39;); $(\u0026#39;#PaymentFrequency\u0026#39;).val(\u0026#39;\u0026#34; + paymentFrequency + \u0026#34;\u0026#39;); $(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0.0055\u0026#39;); $(\u0026#39;#Indexation\u0026#39;).val(\u0026#39;ZeroPercent\u0026#39;); $(\u0026#39;#OngoingCommissionRate\u0026#39;).val(\u0026#39;0.00550\u0026#39;); $(\u0026#39;#ResidualCapitalValueRate\u0026#39;).val(\u0026#39;1.00000\u0026#39;); $(\u0026#39;#JointInvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;); $(\u0026#39;#JointInvestorDetails_GivenNames\u0026#39;).val(\u0026#39;joint test\u0026#39;); $(\u0026#39;#JointInvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;); $(\u0026#39;#JointInvestorDetails_DateOfBirth_day\u0026#39;).val(31); $(\u0026#39;#JointInvestorDetails_DateOfBirth_month\u0026#39;).val(12); $(\u0026#39;#JointInvestorDetails_DateOfBirth_year\u0026#39;).val(1956);\u0026#34;) let greenId = (@\u0026#34; $(\u0026#39;#InvestorDetails_ResidentialAddress_UnitNumber\u0026#39;).val(\u0026#39;5\u0026#39;); $(\u0026#39;#InvestorDetails_ResidentialAddress_StreetNumber\u0026#39;).val(\u0026#39;48\u0026#39;); $(\u0026#39;#InvestorDetails_ResidentialAddress_StreetName\u0026#39;).val(\u0026#39;Manchester\u0026#39;); $(\u0026#39;#InvestorDetails_ResidentialAddress_Suburb\u0026#39;).val(\u0026#39;Gymea\u0026#39;); $(\u0026#39;#InvestorDetails_ResidentialAddress_StreetType\u0026#39;).val(\u0026#39;RD\u0026#39;); $(\u0026#39;#InvestorDetails_ResidentialAddress_State\u0026#39;).val(\u0026#39;NSW\u0026#39;); $(\u0026#39;#InvestorDetails_ResidentialAddress_Postcode\u0026#39;).val(2227); \u0026#34;) let rec deleteFiles srcPath pattern includeSubDirs = if not \u0026lt;| System.IO.Directory.Exists(srcPath) then let msg = System.String.Format(\u0026#34;Source directory does not exist or could not be found: {0}\u0026#34;, srcPath) raise (System.IO.DirectoryNotFoundException(msg)) for file in System.IO.Directory.EnumerateFiles(srcPath, pattern) do let tempPath = System.IO.Path.Combine(srcPath, file) System.IO.File.Delete(tempPath) if includeSubDirs then let srcDir = new System.IO.DirectoryInfo(srcPath) for subdir in srcDir.GetDirectories() do deleteFiles subdir.FullName pattern includeSubDirs ` ","permalink":"https://blog.mckelt.com/articles/posts/f-canopy-ui-tests-httplefthandedgoat-github-iocanopy/","summary":"\u003cp\u003e`\u003c/p\u003e\n\u003ch1 id=\"fsharp-canopy-tests\"\u003eFSharp Canopy Tests\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    namespace RegressionTests\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    open System\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    open System.Configuration\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    open runner\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    open canopy\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    open configuration\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    open reporters\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    open QuoteHelper\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    module QuoteSiteTests =\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        let runTest = (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            start chrome\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let mainBrowser = browser\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            elementTimeout \u0026lt;- 15.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            compareTimeout \u0026lt;- 15.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _testpage =             ConfigurationManager.AppSettings.\\[\u0026#34;AolSiteUrl\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _username =             ConfigurationManager.AppSettings.\\[\u0026#34;AolChallengerId\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _password =             ConfigurationManager.AppSettings.\\[\u0026#34;AolPassword\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _passwordChangeToThis = ConfigurationManager.AppSettings.\\[\u0026#34;AolPasswordChangeToThis\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _includePasswordChangeTest = ConfigurationManager.AppSettings.\\[\u0026#34;IncludePasswordChangeTest\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _quickSearchText = ConfigurationManager.AppSettings.\\[\u0026#34;QuickSearchText\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _quickSearchFindInvestor = ConfigurationManager.AppSettings.\\[\u0026#34;QuickSearchFindInvestor\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            let _path = ConfigurationManager.AppSettings.\\[\u0026#34;OutputTestResults\u0026#34;]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QuoteHelper.deleteFiles _path \u0026#34;\u0026#34; true\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            for file in System.IO.Directory.EnumerateFiles(_path) do\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                let tempPath = System.IO.Path.Combine(_path, file)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                System.IO.File.Delete(tempPath)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            context (\u0026#34;Testing :: eQuote - \u0026#34; + _testpage + \u0026#34;/Quote\u0026#34;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            before (fun _ -\u0026gt; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                  describe \u0026#34;Starting test\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                  url (_testpage + \u0026#34;/Quote\u0026#34;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e           \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ntest \u0026#34;Login\u0026#34; (fun _ -\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                describe (\u0026#34;Login with \u0026#34; + _username)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                url _testpage\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u0026#34;#userId\u0026#34; \u0026lt;\u0026lt; _username\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u0026#34;#password\u0026#34; \u0026lt;\u0026lt;  _password\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                click \u0026#34;.submit\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              //  on (_testpage + \u0026#34;/Secure/Home/\u0026#34;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ntest \u0026#34;GIP Quote - Fixed Term\u0026#34; (fun _ -\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe \u0026#34;Creating GIP quote – fixed 3 year\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]:first\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnContinue1\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let setQuote = QuoteHelper.createQuoteTerm \u0026#34;100000\u0026#34; \u0026#34;Monthly\u0026#34; \u0026#34;3\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js setQuote |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnRunQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnSaveQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let linkText = read \u0026#34;#yourQuoteId\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe linkText\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    screenshot _path linkText |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ntest \u0026#34;GIP quote – life\u0026#34; (fun _ -\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe \u0026#34;Creating GIP quote – life\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]::nth(1)\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnContinue1\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34; $(\u0026#39;input:radio\\[name=ProductTerm]::nth(1)\u0026#39;).click();\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let setQuote = QuoteHelper.createQuoteLife \u0026#34;100000\u0026#34; \u0026#34;Monthly\u0026#34; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js setQuote |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnRunQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnSaveQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let linkText = read \u0026#34;#yourQuoteId\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe linkText\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    screenshot _path linkText |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ntest \u0026#34;GA Quote - Fixed Term\u0026#34; (fun _ -\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe \u0026#34;Creating Fee for service annuity quote - FIXED\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]:first\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnContinue1\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let setQuote = QuoteHelper.createQuoteTerm \u0026#34;100000\u0026#34; \u0026#34;Monthly\u0026#34; \u0026#34;3\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js setQuote |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0.0055\u0026#39;);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnRunQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnSaveQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let linkText = read \u0026#34;#yourQuoteId\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe linkText\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    screenshot _path linkText |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ntest \u0026#34;GA quote – life\u0026#34; (fun _ -\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe \u0026#34;Creating GA quote – life\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]::nth(1)\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnContinue1\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34; $(\u0026#39;input:radio\\[name=ProductTerm]::nth(1)\u0026#39;).click();\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let setQuote = QuoteHelper.createQuoteLife \u0026#34;100000\u0026#34; \u0026#34;Yearly\u0026#34; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js setQuote |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnRunQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnSaveQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let linkText = read \u0026#34;#yourQuoteId\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe linkText\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    screenshot _path linkText |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ntest \u0026#34;GreenId Test\u0026#34; (fun _ -\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe \u0026#34;GreenId Test\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;input:radio\\[name=NewPolicyType]::nth(1)\u0026#39;).attr(\u0026#39;checked\u0026#39;, true);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnContinue1\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34; $(\u0026#39;input:radio\\[name=ProductTerm]::nth(1)\u0026#39;).click();\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let setQuote = QuoteHelper.createQuoteLife \u0026#34;100000\u0026#34; \u0026#34;Yearly\u0026#34; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js setQuote |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js \u0026#34;$(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;);\u0026#34; |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnRunQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnSaveQuote\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    let linkText = read \u0026#34;#yourQuoteId\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    describe linkText\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#btnApply\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    js QuoteHelper.greenId |\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    sleep 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    click \u0026#34;#InvestorDetails_IdentityVerification_CheckId\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    screenshot _path (\u0026#34;GreenId -\u0026#34; + linkText )|\u0026gt; ignore\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            run ()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            quit mainBrowser\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enamespace RegressionTests\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    module QuoteHelper =\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        let createQuoteTerm amount paymentFrequency term = (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                             @\u0026#34;  $(\u0026#39;#InvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_GivenNames\u0026#39;).val(\u0026#39;test\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_DateOfBirth_day\u0026#39;).val(1);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_DateOfBirth_month\u0026#39;).val(1);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_DateOfBirth_year\u0026#39;).val(1937);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestmentAmount\u0026#39;).val(\u0026#34; + amount + \u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestmentAmount_editor\u0026#39;).val(\u0026#39;$100,000.00\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#PaymentFrequency\u0026#39;).val(\u0026#39;\u0026#34; + paymentFrequency + \u0026#34;\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#Term\u0026#39;).val(\u0026#39;\u0026#34; + term + \u0026#34;\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#Indexation\u0026#39;).val(\u0026#39;ZeroPercent\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#OngoingCommissionRate\u0026#39;).val(\u0026#39;0.00550\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#ResidualCapitalValueRate\u0026#39;).val(\u0026#39;1.00000\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_GivenNames\u0026#39;).val(\u0026#39;joint test\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_DateOfBirth_day\u0026#39;).val(31);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_DateOfBirth_month\u0026#39;).val(12);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_DateOfBirth_year\u0026#39;).val(1956);\u0026#34;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        let createQuoteLife amount paymentFrequency  = (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                             @\u0026#34;  $(\u0026#39;#InvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_GivenNames\u0026#39;).val(\u0026#39;test\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_DateOfBirth_day\u0026#39;).val(1);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_DateOfBirth_month\u0026#39;).val(1);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestorDetails_DateOfBirth_year\u0026#39;).val(1937);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestmentAmount\u0026#39;).val(\u0026#34; + amount + \u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InvestmentAmount_editor\u0026#39;).val(\u0026#39;$100,000.00\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#PaymentFrequency\u0026#39;).val(\u0026#39;\u0026#34; + paymentFrequency + \u0026#34;\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#InitialCommissionRate\u0026#39;).val(\u0026#39;0.0055\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#Indexation\u0026#39;).val(\u0026#39;ZeroPercent\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#OngoingCommissionRate\u0026#39;).val(\u0026#39;0.00550\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#ResidualCapitalValueRate\u0026#39;).val(\u0026#39;1.00000\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_Title\u0026#39;).val(\u0026#39;Mr\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_GivenNames\u0026#39;).val(\u0026#39;joint test\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_Surname\u0026#39;).val(\u0026#39;client\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_DateOfBirth_day\u0026#39;).val(31);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_DateOfBirth_month\u0026#39;).val(12);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            $(\u0026#39;#JointInvestorDetails_DateOfBirth_year\u0026#39;).val(1956);\u0026#34;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        let greenId = (@\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $(\u0026#39;#InvestorDetails_ResidentialAddress_UnitNumber\u0026#39;).val(\u0026#39;5\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $(\u0026#39;#InvestorDetails_ResidentialAddress_StreetNumber\u0026#39;).val(\u0026#39;48\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $(\u0026#39;#InvestorDetails_ResidentialAddress_StreetName\u0026#39;).val(\u0026#39;Manchester\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $(\u0026#39;#InvestorDetails_ResidentialAddress_Suburb\u0026#39;).val(\u0026#39;Gymea\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $(\u0026#39;#InvestorDetails_ResidentialAddress_StreetType\u0026#39;).val(\u0026#39;RD\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $(\u0026#39;#InvestorDetails_ResidentialAddress_State\u0026#39;).val(\u0026#39;NSW\u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $(\u0026#39;#InvestorDetails_ResidentialAddress_Postcode\u0026#39;).val(2227);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026#34;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        let rec deleteFiles srcPath pattern includeSubDirs =\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            if not \u0026lt;| System.IO.Directory.Exists(srcPath) then\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                let msg = System.String.Format(\u0026#34;Source directory does not exist or could not be found: {0}\u0026#34;, srcPath)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                raise (System.IO.DirectoryNotFoundException(msg))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                for file in System.IO.Directory.EnumerateFiles(srcPath, pattern) do\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                let tempPath = System.IO.Path.Combine(srcPath, file)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                System.IO.File.Delete(tempPath)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                if includeSubDirs then\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                let srcDir = new System.IO.DirectoryInfo(srcPath)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                for subdir in srcDir.GetDirectories() do\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                deleteFiles subdir.FullName pattern includeSubDirs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e`           \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"F# Canopy UI tests -- http://lefthandedgoat.github.io/canopy/"},{"content":"Function Get-SvnLogData() { ([xml](svn log -v --xml \u0026#39;http://svn/trunk\u0026#39;)).log.logentry | % { $nestedEntry = $_ $_.paths.path | % { $path = $_ $nestedEntry | Select-Object -Property ` Author, ` @{n=\u0026#39;Revision\u0026#39;; e={([int]$_.Revision)}}, ` @{n=\u0026#39;Date\u0026#39;; e={Get-Date $_.Date }}, ` @{n=\u0026#39;Action\u0026#39;; e={$path.action }}, ` @{n=\u0026#39;Path\u0026#39;; e={$path.InnerText }}` } } } Get-SvnLogData | where { $_.Date -ge (Get-Date \u0026#39;16-04-2013\u0026#39;) } | Select-Object Revision,Date,Path,Author | sort -property ` @{ Expression=\u0026#34;Path\u0026#34;; Descending=$false }, ` @{ Expression=\u0026#34;Revision\u0026#34;; Descending=$true } | Export-CSV c:\\test.csv ","permalink":"https://blog.mckelt.com/articles/posts/powershell-svn-export-files-to-csv/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFunction Get-SvnLogData()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ([xml](svn log -v --xml  \u0026#39;http://svn/trunk\u0026#39;)).log.logentry | % {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $nestedEntry = $_\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $_.paths.path | % {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $path = $_\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $nestedEntry | Select-Object -Property `\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Author, `\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                @{n=\u0026#39;Revision\u0026#39;; e={([int]$_.Revision)}}, `\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                @{n=\u0026#39;Date\u0026#39;;     e={Get-Date $_.Date  }}, `\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                @{n=\u0026#39;Action\u0026#39;;   e={$path.action      }}, `\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                @{n=\u0026#39;Path\u0026#39;;     e={$path.InnerText   }}`\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGet-SvnLogData |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewhere { $_.Date -ge (Get-Date \u0026#39;16-04-2013\u0026#39;) } |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSelect-Object  Revision,Date,Path,Author | \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esort -property `\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    @{ Expression=\u0026#34;Path\u0026#34;;     Descending=$false }, `\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    @{ Expression=\u0026#34;Revision\u0026#34;; Descending=$true  } |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExport-CSV c:\\test.csv\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Powershell \u0026 SVN – Export files to CSV"},{"content":"13 Steps to exception presentation design Pace, Pace, Pace Lead WIIFM (What’s in it for me?) – Reduce Maintain Improve POO (Pacing Out Objectives) Frame - (i.e. Agenda Other Speakers) What (from 4Mat) How (from 4Mat) - Other info “by the way” my pleasure Contact Details Summary (why, what, how) Call to action QA Negative \u0026amp; Positive Closing Statement ","permalink":"https://blog.mckelt.com/articles/posts/13-steps-to-exception-presentation-design-from-httpmichellebowden-com-au/","summary":"\u003ch2 id=\"13-steps-to-exception-presentation-design\"\u003e13 Steps to exception presentation design\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003ePace, Pace, Pace\u003c/li\u003e\n\u003cli\u003eLead\u003c/li\u003e\n\u003cli\u003eWIIFM (What’s in it for me?) – Reduce Maintain Improve\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://michellebowden.com.au/2012/05/27-things-every-engineer-needs-to-know-about-influencing-their-stakeholders/\" target=\"_blank\"\u003ePOO\u003c/a\u003e (Pacing Out Objectives)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://michellebowden.com.au/2012/05/understanding-others-internalexternal-frame-of-reference/\" target=\"_blank\"\u003eFrame\u003c/a\u003e -  (i.e. Agenda Other Speakers)\u003c/li\u003e\n\u003cli\u003eWhat (from \u003ca href=\"http://michellebowden.com.au/2013/01/how-can-people-develop-more-confidence-when-presenting-in-front-of-an-audience/\" target=\"_blank\"\u003e4Mat\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eHow (from \u003ca href=\"http://michellebowden.com.au/2013/01/how-can-people-develop-more-confidence-when-presenting-in-front-of-an-audience/\" target=\"_blank\"\u003e4Mat\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e-\n\u003col\u003e\n\u003cli\u003eOther info “by the way”\u003c/li\u003e\n\u003cli\u003emy pleasure\u003c/li\u003e\n\u003cli\u003eContact Details\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003eSummary (why, what, how)\u003c/li\u003e\n\u003cli\u003eCall to action\u003c/li\u003e\n\u003cli\u003eQA\u003c/li\u003e\n\u003cli\u003eNegative \u0026amp; Positive\u003c/li\u003e\n\u003cli\u003eClosing Statement\u003c/li\u003e\n\u003c/ol\u003e","title":"13 Steps to exception presentation design (from http://michellebowden.com.au/)"},{"content":"Overview This dataset contains all irregular verbs in all known Romance languages—including Portugese, Spanish, French, and Italian. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\nView dataset Irregular verbs in Portugese: data Irregular verbs in Italian: data Irregular verbs in French: data Irregular verbs in Spanish: data Source of data Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\nUsing data with Python Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\nStart Python: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nimport numpy as np import pandas as pd Open the file: Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat data.csv.\nfile_path = \u0026#39;data.csv\u0026#39; with open(file_path, \u0026#39;r\u0026#39;) as file: Read data: Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nlines = file.readlines() Parse and process data: Duis aute line_data irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur data.extend.\ndata = [] for line in lines: line_data = line.strip().split(\u0026#39;,\u0026#39;) # Split the line into a list of values line_data = [float(value) for value in line_data] # Convert values to floats data.extend(line_data) # Extend the main list with values from the line Compute summary statistics using NumPy: Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum: data_array.\ndata_array = np.array(data) # Convert the list to a NumPy array mean = np.mean(data_array) median = np.median(data_array) std_dev = np.std(data_array) min_value = np.min(data_array) max_value = np.max(data_array) Display summary statistics: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat print.\nprint(f\u0026#34;Mean: {mean}\u0026#34;) print(f\u0026#34;Median: {median}\u0026#34;) print(f\u0026#34;Standard Deviation: {std_dev}\u0026#34;) print(f\u0026#34;Minimum Value: {min_value}\u0026#34;) print(f\u0026#34;Maximum Value: {max_value}\u0026#34;) Description of simulation parameters Parameter Value Language Time period Description $\\alpha$ $1/2$ French 1930–1954 Tempor dolor in $\\lambda$ $e/2$ French 1930–1954 Fugiat sint occaecat $\\gamma$ $\\ln(3)$ Spanish 1833–1954 Duis officia deserunt $\\omega$ $10^{-4}$ Italian 1930–1994 Excepteur et dolore magna aliqua $\\sigma$ $1.5$ Portuguese 1990–2023 Lorem culpa qui $\\chi^2$ $\\pi^2$ Portuguese 1990–2023 Labore et dolore ","permalink":"https://blog.mckelt.com/data/data1/","summary":"This dataset contains all irregular verbs in known Romance languages.","title":"List of Irregular Verbs Across Romance Languages"},{"content":"NServiceBus PowerShell Install $Arguments = \u0026#39;/install /startManually /serviceName:{0} /displayName:{0} NServiceBus.Production /username:{1} /password:{2}\u0026#39; -f \u0026#39;McKelt.securitytokenservice.nservicebus.messagehandler\u0026#39;, \u0026#39;xxxx@au.McKelt.net\u0026#39;, \u0026#39;PasswordGoesHere\u0026#39; $nServiceBus = Resolve-Path -Path nServiceBus.Host.exe; Write-Host -Object (\u0026#39;Argument string is: {0}\u0026#39; -f $Arguments); Write-Host -Object (\u0026#39;Path to nServiceBus.Host.exe is: {0}\u0026#39; -f $nServiceBus); Start-Process -Wait -NoNewWindow -FilePath $nServiceBus -ArgumentList $Arguments -RedirectStandardOutput tmp.txt; ","permalink":"https://blog.mckelt.com/articles/posts/nservicebus-powershell-install/","summary":"\u003ch2 id=\"nservicebus-powershell-install\"\u003eNServiceBus PowerShell Install\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$Arguments = \u0026#39;/install /startManually /serviceName:{0} /displayName:{0} NServiceBus.Production /username:{1} /password:{2}\u0026#39; -f \u0026#39;McKelt.securitytokenservice.nservicebus.messagehandler\u0026#39;, \u0026#39;xxxx@au.McKelt.net\u0026#39;, \u0026#39;PasswordGoesHere\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$nServiceBus = Resolve-Path -Path nServiceBus.Host.exe;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWrite-Host -Object (\u0026#39;Argument string is: {0}\u0026#39; -f $Arguments);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWrite-Host -Object (\u0026#39;Path to nServiceBus.Host.exe is: {0}\u0026#39; -f $nServiceBus);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eStart-Process -Wait -NoNewWindow -FilePath $nServiceBus -ArgumentList $Arguments -RedirectStandardOutput tmp.txt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"NServiceBus Powershell Install"},{"content":" function Remove-MailItem { [CmdletBinding(SupportsShouldProcess=$true)] param ( [parameter(Mandatory=$true)] [string]$mailfolder, [string]$parentfolder ) $ol = new-object -comobject \u0026#34;Outlook.Application\u0026#34;; # Map to the MAPI namespace $mapi = $ol.getnamespace(\u0026#34;mapi\u0026#34;); $targetfolder = \u0026#39;\u0026#39; if ($parentfolder.Length -eq 0) { $targetfolder = $mapi.Folders.Item(1).Folders.Item(\u0026#34;Inbox\u0026#34;).Folders.Item($mailfolder) } else { $targetfolder = $mapi.Folders.Item(1).Folders.Item(\u0026#34;Inbox\u0026#34;).Folders.Item($parentfolder).Folders.Item($mailfolder) } foreach ($item in $targetfolder.Items) { try { $item.Delete() } catch [Exception]{ Write-Host \u0026#34;Failed to delete item: \u0026#34; + $item.Subject Write-Host $_.Exception.ToString() } } function Clear-DeletedMail { $outlook = New-Object -ComObject Outlook.Application foreach ($folder in $outlook.Session.Folders){ foreach($mailfolder in $folder.Folders ) { if ($mailfolder.Name -eq \u0026#34;Deleted Items\u0026#34; -and $mailfolder.Items.Count -gt 0){ foreach ($item in $mailfolder.Items){$item.Delete()} } } } } } Remove-MailItem -mailfolder \u0026#34;Cafe\u0026#34; Remove-MailItem -mailfolder \u0026#34;COLSupport\u0026#34; Remove-MailItem -mailfolder \u0026#34;Failed Logins\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34; Remove-MailItem -mailfolder \u0026#34;IISReset\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34; Remove-MailItem -mailfolder \u0026#34;Not Urgent\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34; Remove-MailItem -mailfolder \u0026#34;Production\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34; ","permalink":"https://blog.mckelt.com/articles/posts/powershell-script-to-delete-mail-from-specific-folder/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efunction Remove-MailItem {            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t[CmdletBinding(SupportsShouldProcess=$true)]            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eparam (            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e [parameter(Mandatory=$true)]            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e [string]$mailfolder,                    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e [string]$parentfolder                                 \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e)            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ol = new-object -comobject \u0026#34;Outlook.Application\u0026#34;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# Map to the MAPI namespace\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$mapi = $ol.getnamespace(\u0026#34;mapi\u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$targetfolder  = \u0026#39;\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eif ($parentfolder.Length -eq 0)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t$targetfolder = $mapi.Folders.Item(1).Folders.Item(\u0026#34;Inbox\u0026#34;).Folders.Item($mailfolder)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eelse\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t$targetfolder = $mapi.Folders.Item(1).Folders.Item(\u0026#34;Inbox\u0026#34;).Folders.Item($parentfolder).Folders.Item($mailfolder)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eforeach ($item in $targetfolder.Items)  {     \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\ttry {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t$item.Delete()       \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\tcatch [Exception]{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\tWrite-Host \u0026#34;Failed to delete item: \u0026#34; + $item.Subject\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\tWrite-Host $_.Exception.ToString()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efunction Clear-DeletedMail {            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$outlook = New-Object -ComObject Outlook.Application            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eforeach ($folder in $outlook.Session.Folders){            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  foreach($mailfolder in $folder.Folders ) {            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    if ($mailfolder.Name -eq \u0026#34;Deleted Items\u0026#34; -and $mailfolder.Items.Count -gt 0){            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      foreach ($item in $mailfolder.Items){$item.Delete()}            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }               \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }             \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRemove-MailItem -mailfolder \u0026#34;Cafe\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRemove-MailItem -mailfolder \u0026#34;COLSupport\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRemove-MailItem -mailfolder \u0026#34;Failed Logins\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRemove-MailItem -mailfolder \u0026#34;IISReset\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRemove-MailItem -mailfolder \u0026#34;Not Urgent\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRemove-MailItem -mailfolder \u0026#34;Production\u0026#34; -parentfolder \u0026#34;COLSupport\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120943129-9de84e80-c75f-11eb-8afe-d55f54735e3f.png\"\u003e\u003c/p\u003e","title":"Powershell script to delete mail from specific folder"},{"content":"Software Quotes “In God we trust. All others must bring data.”- W. Edwards Deming, Statistician\n“Web users ultimately want to get at data quickly and easily. They don’t care as much about attractive sites and pretty design.”- Tim Berners-Lee\nNot everything that can be counted counts, and not everything that counts can be counted. William Bruce Cameron (not Albert Einstein)\nWithout An Opinion, You\u0026rsquo;re Just Another Person With Data - W. Edwards Deming\n","permalink":"https://blog.mckelt.com/articles/posts/software-quotes/","summary":"\u003ch1 id=\"software-quotes\"\u003eSoftware Quotes\u003c/h1\u003e\n\u003cp\u003e“In God we trust. All others must bring data.”- \u003cem\u003e\u003ca href=\"https://www.google.com/url?q=https://en.wikipedia.org/wiki/W._Edwards_Deming\u0026amp;sa=D\u0026amp;ust=1463700706970000\u0026amp;usg=AFQjCNGZqsO5eD2PW7Zhcjxo-i92jAVjcw\" target=\"_blank\"\u003eW. Edwards Deming\u003c/a\u003e, Statistician\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e“Web users ultimately want to get at data quickly and easily. They don’t care as much about attractive sites and pretty design.”- \u003cem\u003e\u003ca href=\"https://www.google.com/url?q=https://www.w3.org/People/Berners-Lee/\u0026amp;sa=D\u0026amp;ust=1463700706975000\u0026amp;usg=AFQjCNGk--KPQzu4EBokEcraVCA8ixurnQ\" target=\"_blank\"\u003eTim Berners-Lee\u003c/a\u003e\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eNot everything that can be counted counts, and not everything that counts can be counted. \u003ca href=\"http://quoteinvestigator.com/2010/05/26/everything-counts-einstein/\" title=\"Albert Einstein\" target=\"_blank\"\u003eWilliam Bruce Cameron (not Albert Einstein)\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWithout An Opinion, You\u0026rsquo;re Just Another Person With Data - W. Edwards Deming\u003c/p\u003e","title":"Software quotes"},{"content":"Using https://github.com/chucknorris/roundhouse for powershell to get automated database change management\nTask UpgradeDatabase{ if (($environment -eq 'integration') -or ($environment -eq 'uat')) { # round house variables $rh = \u0026quot;C:\\\\dev\\\\Phoenix\\\\trunk\\\\Tools\\\\RoundhousE\\\\console\\\\rh.exe\u0026quot; $connectionString = \u0026quot;Data Source=localhost;Database=XXX; User Id=XXXuser; Password=XXX;Connect Timeout=100;\u0026quot; $indexesFolder = \u0026quot;C:\\\\dev\\\\Phoenix\\\\trunk\\\\Database\\\\10-Indexes\u0026quot; $schemaChangesFolder = \u0026quot;C:\\\\dev\\\\Phoenix\\\\trunk\\\\Database\\\\11-SchemaChanges\u0026quot; ## build server? if (Test-Path \u0026quot;D:\\\\Code\\\\\u0026quot;) { $rh = \u0026quot;D:\\\\Code\\\\Phoenix\\\\trunk\\\\Tools\\\\RoundhousE\\\\console\\\\rh.exe\u0026quot; $indexesFolder = \u0026quot;D:\\\\Code\\\\Phoenix\\\\trunk\\\\Database\\\\10-Indexes\u0026quot; $schemaChangesFolder = \u0026quot;D:\\\\Code\\\\Phoenix\\\\trunk\\\\Database\\\\11-SchemaChanges\u0026quot; if ($environment -eq 'integration') { $connectionString = \u0026quot;Data Source=xxxxx;Database=rrrr\\_Integration; User Id=rrrr; Password=rrrr;\u0026quot; } else { $connectionString = \u0026quot;Data Source=xxxx;Database=rrrrr\\_UAT; User Id=rrrrr; Password=rrrrr;\u0026quot; } } Write\\-Host \u0026quot;Database upgrade started\u0026quot; $s1 = \u0026quot; -c \u0026quot; $s2 = \u0026quot; $connectionString \u0026quot; $s3 = \u0026quot; -ix \u0026quot; $s4 = \u0026quot;$indexesFolder\u0026quot; $s5 = \u0026quot; -u \u0026quot; $s6 = \u0026quot;$schemaChangesFolder\u0026quot; $args = $s1 + \u0026quot; \u0026quot;\u0026quot;$s2\u0026quot; \u0026quot;\u0026quot; + $s3 + \u0026quot; \u0026quot;\u0026quot;$s4\u0026quot; \u0026quot;\u0026quot; + $s5 + \u0026quot; \u0026quot;\u0026quot;$s6\u0026quot;\u0026quot;\u0026quot; + \u0026quot; -ni -ct 300\u0026quot; Write\\-Host $args Start-Process -FilePath $rh -ArgumentList $args -PassThru Write\\-Host \u0026quot;Database upgrade complete\u0026quot;\t} } The following tables are created\nWith the following scripts run\n","permalink":"https://blog.mckelt.com/articles/posts/round-house-and-powershell/","summary":"\u003cp\u003eUsing \u003ca href=\"https://github.com/chucknorris/roundhouse\" title=\"https://github.com/chucknorris/roundhouse\" target=\"_blank\"\u003ehttps://github.com/chucknorris/roundhouse\u003c/a\u003e for powershell to get automated database change management\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eTask UpgradeDatabase{\n\nif (($environment -eq  'integration') -or ($environment -eq  'uat'))\n{\n\t# round house variables\n\t$rh = \u0026quot;C:\\\\dev\\\\Phoenix\\\\trunk\\\\Tools\\\\RoundhousE\\\\console\\\\rh.exe\u0026quot;\n\t$connectionString = \u0026quot;Data Source=localhost;Database=XXX; User Id=XXXuser; Password=XXX;Connect Timeout=100;\u0026quot;\n\t$indexesFolder = \u0026quot;C:\\\\dev\\\\Phoenix\\\\trunk\\\\Database\\\\10-Indexes\u0026quot;\n\t$schemaChangesFolder = \u0026quot;C:\\\\dev\\\\Phoenix\\\\trunk\\\\Database\\\\11-SchemaChanges\u0026quot;\n\t## build server?\n\tif (Test-Path \u0026quot;D:\\\\Code\\\\\u0026quot;) \n\t{\n\t\t$rh = \u0026quot;D:\\\\Code\\\\Phoenix\\\\trunk\\\\Tools\\\\RoundhousE\\\\console\\\\rh.exe\u0026quot;\n\t\t$indexesFolder = \u0026quot;D:\\\\Code\\\\Phoenix\\\\trunk\\\\Database\\\\10-Indexes\u0026quot;\n\t\t$schemaChangesFolder = \u0026quot;D:\\\\Code\\\\Phoenix\\\\trunk\\\\Database\\\\11-SchemaChanges\u0026quot;\n\t\tif ($environment -eq  'integration')\n\t\t{\n\t\t\t$connectionString = \u0026quot;Data Source=xxxxx;Database=rrrr\\_Integration; User Id=rrrr; Password=rrrr;\u0026quot;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$connectionString = \u0026quot;Data Source=xxxx;Database=rrrrr\\_UAT; User Id=rrrrr; Password=rrrrr;\u0026quot;\n\t\t}\n\t}\n\n\tWrite\\-Host \u0026quot;Database upgrade started\u0026quot;\n\n\t$s1 = \u0026quot; -c \u0026quot;\n\t$s2 = \u0026quot; $connectionString \u0026quot;\n\t$s3 = \u0026quot; -ix \u0026quot;\n\t$s4 = \u0026quot;$indexesFolder\u0026quot;\n\t$s5 = \u0026quot; -u \u0026quot;\n\t$s6 = \u0026quot;$schemaChangesFolder\u0026quot; \n\n\t$args = $s1 +  \u0026quot; \u0026quot;\u0026quot;$s2\u0026quot; \u0026quot;\u0026quot;  + $s3  + \u0026quot; \u0026quot;\u0026quot;$s4\u0026quot; \u0026quot;\u0026quot; +  $s5 +  \u0026quot; \u0026quot;\u0026quot;$s6\u0026quot;\u0026quot;\u0026quot; + \u0026quot; -ni -ct 300\u0026quot;\n\n\tWrite\\-Host $args\n\n\tStart-Process -FilePath $rh -ArgumentList $args -PassThru\n\n\tWrite\\-Host \u0026quot;Database upgrade complete\u0026quot;\t\n}  \n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e \nThe following tables are created\u003c/p\u003e","title":"Round house and powershell"},{"content":"This is a quick post to show how to get PowerShell with PSAKE to run Specflow acceptance tests on the build server using Gallio.\nhttps://github.com/chrismckelt/PS-Sake-BuildScripts\nThe folder with our build scripts looks like this\nThe environments folder contains all of the configuration files for each environment\nBuild server process The build/check-in process is now as follows.\n1. Developer checks in.\n2. Build server detects changes – cleans everything and then pulls down latest SVN code\n3. Cruise control builds code in release mode –\u0026gt; If compile fails –\u0026gt; build fail\n4. Unit tests run in place à if any test fails –\u0026gt; build fail\n5. On success a new folder with the VERSION number is created \u0026mdash; this is our artefacts\n6. This build is then deployed to the integration server and the Acceptance tests are run – Results are output to a folder\n7. If the Acceptance tests fails -\u0026gt; build fail\n8. On Success the build is packaged for deployment (config files modified for environment)\nCruise control originally calls default.ps1 passing in the environment.\n\u0026lt;\u0026lsquo;powershell\u0026rsquo;\u0026gt;\n\u0026lt;\u0026lsquo;scriptsDirectory\u0026rsquo;\u0026gt;C:\\CCWorking\\Phoenix\\CodeBase\\Build\\BuildScripts\u0026lt;/\u0026lsquo;scriptsDirectory\u0026rsquo;\u0026gt;\n\u0026lt; \u0026lsquo;script\u0026rsquo; \u0026gt;default.ps1\u0026lt;/\u0026lsquo;script\u0026rsquo; \u0026gt;\n\u0026lt;\u0026lsquo;buildArgs\u0026rsquo;\u0026gt;-environment:integration\u0026lt;/\u0026lsquo;buildArgs\u0026rsquo;\u0026gt;\n\u0026lt;\u0026lsquo;executable\u0026rsquo;\u0026gt;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\u0026lt;/\u0026rsquo;executable\u0026rsquo;\u0026gt;\n\u0026lt;\u0026lsquo;buildTimeoutSeconds\u0026rsquo;\u0026gt;10000\u0026lt;/\u0026lsquo;buildTimeoutSeconds\u0026rsquo;\u0026gt; \u0026lt;\u0026lsquo;description\u0026rsquo;\u0026gt;Phoenix Build\u0026lt;/\u0026lsquo;description\u0026rsquo;\u0026gt; \u0026lt;/\u0026lsquo;powershell\u0026rsquo;\u0026gt;\nThis calls build.ps1\nPSAKE tasks include\nTask default -depends PrintInformation, CleanEnvironment, Clean, SetupEnvironment, MakeBuild, BuildDatabase, DeployIntegrationBuild, IntegrationTest, DeployBuild, UpdateConfigFiles To run the acceptance tests using Gallio The following Powershell function is used:@\nUsage for Gallio tests:\n_Task Test-System -Description \u0026quot;Runs the system tests via Gallio\u0026quot; { Test-Gallio $proj $configuration $platform $dll \u0026quot;system\u0026quot; \u0026quot;Test.System\u0026quot; # Test-Gallio \u0026quot;.\\\\src\\\\Test.Unit\\\\Test.Unit.csproj\u0026quot; Release x64 \u0026quot;.\\\\src\\\\Test.Unit\\\\bin\\\\Release\\\\x64\\\\Test.Unit.dll\u0026quot; \u0026quot;unit\u0026quot; } } #\u0026gt; function Test-Gallio($proj, $configuration, $platform, $dll, $report\\_name, $report\\_dir, $namespace\\_filter){ Write-Host \u0026quot;GALLIO TEST proj -- $proj\u0026quot; Write-Host \u0026quot;GALLIO TEST configuration -- $configuration\u0026quot; Write-Host \u0026quot;GALLIO TEST platform -- $platform\u0026quot; Write-Host \u0026quot;GALLIO TEST dll -- $dll\u0026quot; Write-Host \u0026quot;GALLIO TEST report\\_name -- $report\\_name\u0026quot; Write-Host \u0026quot;GALLIO TEST namespace\\_filter -- $namespace\\_filter\u0026quot;_ _if ( (Get-PSSnapin -Name Gallio -ErrorAction SilentlyContinue) -eq $null ) { Add-PSSnapin Gallio } $result = Run-Gallio $dll -filter Namespace:/$namespace\\_filter/ -ReportTypes text,html,xml -ReportDirectory $report\\_dir -ReportNameFormat $report\\_name-test-report #-NoProgress -NoEchoResults get-content \u0026quot;$report\\_dir\\\\$report\\_name-test-report.txt\u0026quot; | Write-Host Write-Host $result.ResultsSummary if ($result.Statistics.FailedCount -gt 0) { Write-Warning \u0026quot;Some unit tests have failed.\u0026quot; $Error = $result.ResultsSummary exit $result.ResultCode } Remove-PSSnapin Gallio }_ From an acceptance test entered into SpecFlow as follows:\nOn checkin the build will run and output the result of this test in a report called AcceptanceTests-test-report.html\n","permalink":"https://blog.mckelt.com/articles/posts/psake-gallio-specflow-xunit-on-the-build-server-2/","summary":"\u003cp\u003eThis is a quick post to show how to get PowerShell with \u003ca href=\"http://codebetter.com/jameskovacs/2010/04/12/psake-v4-00/\" target=\"_blank\"\u003ePSAKE\u003c/a\u003e to run \u003ca href=\"http://specflow.org/\" target=\"_blank\"\u003eSpecflow\u003c/a\u003e acceptance tests on the build server using \u003ca href=\"http://www.gallio.org/\" target=\"_blank\"\u003eGallio\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/chrismckelt/PS-Sake-BuildScripts\" title=\"https://github.com/chrismckelt/PS-Sake-BuildScripts\" target=\"_blank\"\u003ehttps://github.com/chrismckelt/PS-Sake-BuildScripts\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThe folder with our build scripts looks like this\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120942836-06363080-c75e-11eb-9e2f-0a43b021e334.png\"\u003e\u003c/p\u003e\n\u003cp\u003eThe environments folder contains all of the configuration files for each environment\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120924073-7021ec00-c704-11eb-83f0-c51328e36f54.png\"\u003e\u003c/p\u003e\n\u003cp\u003eBuild server process\n \u003c/p\u003e\n\u003cp\u003eThe build/check-in process is now as follows.\u003c/p\u003e\n\u003cp\u003e1. Developer checks in.\u003c/p\u003e\n\u003cp\u003e2. Build server detects changes – cleans everything and then pulls down latest SVN code\u003c/p\u003e","title":"PSAKE- Gallio–SpecFlow–XUnit–on the build server"},{"content":"Technical Test - Book Store An online books store sells books for 3 different categories: Crime, Romance, Fantasy.\nCurrently all books within the Crime category are discounted by 5%\nTotal tax for the whole order is 10%\nThe task Write a simple console application that outputs the total order cost with and without tax for the below purchase:\nBook name Category Total Cost Unsolved crimes Crime 10.99 A Little Love Story Romance 2.40 Heresy Fantasy 6.80 Jack the Ripper Crime 16.00 The Tolkien Years Fantasy 22.90 Guidelines\nThe application should be runnable in Visual Studio / Code via F5 The code should be accessible on the public/private Git repo. Hint: you could manually calculate your answer first to confirm your logic is sound!\n","permalink":"https://blog.mckelt.com/articles/posts/interview-code-test/","summary":"\u003ch1 id=\"technical-test---book-store\"\u003e\u003cstrong\u003eTechnical Test - Book Store\u003c/strong\u003e\u003c/h1\u003e\n\u003cp\u003eAn online books store sells books for 3 different categories: \u003cem\u003eCrime, Romance, Fantasy.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eCurrently all books within the Crime category are discounted by 5%\u003c/p\u003e\n\u003cp\u003eTotal tax for the whole order is 10%\u003c/p\u003e\n\u003ch2 id=\"the-task\"\u003e\u003cstrong\u003eThe task\u003c/strong\u003e\u003c/h2\u003e\n\u003cp\u003eWrite a simple console application that outputs the total order cost with and without tax for the below purchase:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eBook name\u003c/th\u003e\n          \u003cth\u003eCategory\u003c/th\u003e\n          \u003cth\u003eTotal Cost\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eUnsolved crimes\u003c/td\u003e\n          \u003ctd\u003eCrime\u003c/td\u003e\n          \u003ctd\u003e10.99\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eA Little Love Story\u003c/td\u003e\n          \u003ctd\u003eRomance\u003c/td\u003e\n          \u003ctd\u003e2.40\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eHeresy\u003c/td\u003e\n          \u003ctd\u003eFantasy\u003c/td\u003e\n          \u003ctd\u003e6.80\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eJack the Ripper\u003c/td\u003e\n          \u003ctd\u003eCrime\u003c/td\u003e\n          \u003ctd\u003e16.00\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eThe Tolkien Years\u003c/td\u003e\n          \u003ctd\u003eFantasy\u003c/td\u003e\n          \u003ctd\u003e22.90\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003eGuidelines\u003c/strong\u003e\u003c/p\u003e","title":"My interview coding test"},{"content":"Using SpecFlow heres how I solved the following problem\nPROBLEM : SALES TAXES Basic sales tax is applicable at a rate of 10% on all goods, except books, food, and medical products that are exempt. Import duty is an additional sales tax applicable on all imported goods at a rate of 5%, with no exemptions._\nWhen I purchase items I receive a receipt which lists the name of all the items and their price (including tax), finishing with the total cost of the items, and the total amounts of sales taxes paid. The rounding rules for sales tax are that for a tax rate of n%, a shelf price of p contains (np/100 rounded up to the nearest 0.05) amount of sales tax.\nWrite an application that prints out the receipt details for these shopping baskets\u0026hellip;\nINPUT: Input 1: 1 book at 12.49 1 music CD at 14.99 1 chocolate bar at 0.85 Input 2: 1 imported box of chocolates at 10.00 1 imported bottle of perfume at 47.50 Input 3: 1 imported bottle of perfume at 27.99 1 bottle of perfume at 18.99 1 packet of headache pills at 9.75 1 box of imported chocolates at 11.25 OUTPUT Output 1: 1 book : 12.49 1 music CD: 16.49 1 chocolate bar: 0.85 Sales Taxes: 1.50 Total: 29.83 Output 2: 1 imported box of chocolates: 10.50 1 imported bottle of perfume: 54.65 Sales Taxes: 7.65 Total: 65.15 Output 3: 1 imported bottle of perfume: 32.19 1 bottle of perfume: 20.89 1 packet of headache pills: 9.75 1 imported box of chocolates: 11.85 Sales Taxes: 6.70 Total: 74.68 ========== A Quick overview of the application The solution is a console application that parses given files (i.e. Input1.txt) and creates an output formatted as requested in the problem.\nIt looks like this:\nProjects SalesTaxApplication \u0026ndash; Console Application that imports text files ie input1.txt \u0026ndash; these a copied to the bin folder at compile time \u0026ndash; but you just just pass in a file path McKelt.SalesTaxApplication [/s filename] \u0026ndash; McKelt.SalesTaxApplication /s input3.txt Domain \u0026ndash; contains core model \u0026amp; other shared classes Acceptance Tests \u0026ndash; uses SpecFlow for BDD acceptance tests - was hoping to have reusable steps but didnt get round to this sorry \u0026ndash; http://stackoverflow.com/questions/5228030/specflow-re-usable-step-definitions Unit Tests \u0026ndash; used MBUnit with Resharper for testing TDD style\nDesign I choose to use a state pattern for managing the order object. As the order transitions to completed I choose to use chained commands to execute tasks So once the order is complete the following commands are kicked off:\n\u0026ndash; CalculateSalesTaxCommand\n\u0026ndash; CalculateImportedSalesTaxCommand\n\u0026ndash; CalculateTotalCostWithoutTaxCommand\nProbably YAGNI but this is just a demo\nOther NuGet used to get the following packages. Args, Command Line processor, Castle.Core Castle.Windsor, Rhino Mocks, MBUnit, SpecFlow SoftwareApproach.TestingExtensions, VisualStudioTestingExtensions.1.1.0.0\nSystemWrapper used to wrap all IO calls for ease of testing \u0026ndash; http://systemwrapper.codeplex.com/\nThe order can be seen below – its contains a CurrentState object that manages he order process:\npublic class Order { public Order() { OrderItems = new List\u0026lt;OrderItem\\\u0026gt;(); this.CurrentState = new NotCreated(this); } public virtual int Id { get; set; } public virtual string Name { get; set; } public IList\u0026lt;OrderItem\\\u0026gt; OrderItems { get; set; } public virtual IOrderState CurrentState { get; set; } public Decimal TotalTax { get; set; } public Decimal TotalCostWithoutTax { get; set; } public decimal TotalOrderCost { get { return TotalTax + TotalCostWithoutTax; } } public virtual void AddProduct(Product product) { AddProduct(product, 1); } public virtual void AddProduct(Product product, int quantity) { var oi = new OrderItem { Product = product, Quantity = quantity }; if (OrderItems.Any(a=\u0026gt;a.Product.Id == product.Id)) { int originalQuantity = OrderItems.Single(a =\u0026gt; a.Product.Id == product.Id).Quantity; OrderItems.Single(a =\u0026gt; a.Product.Id == product.Id).Quantity = (originalQuantity + quantity); } else { OrderItems.Add(oi); } } public virtual void Become(IOrderState orderState) { orderState.BecomeCommands.Execute(); CurrentState.Become(orderState); } }\nThe states the order can be in are:\nNotCreated Created Completed As the order moves to its next stage a chain of commands is kicked off.\nNotCreated – NoCommand (does nothing) Created – NoCommand (does nothing) Completed \u0026ndash; CalculateSalesTaxCommand, CalculateImportedSalesTaxCommand, CalculateTotalCostWithoutTaxCommand –\u0026gt; run in order these do the calculations In starting development, I started with the BDD Acceptance test – this runs red so then I develop unit tests which after red/green/refactor I rerun the acceptance test which goes green\nHere is the Spec flow feature file for the order creation\nFeature: Customer Order Creation To create an order As a user I enter the customers details And the Order is created\n@CustomerOrderCreation Scenario: Create an order Given a Customer When the Customers name is Test Customer When I create an order Then a new order is created\nAnds here the BDD code file\n[Binding] public class CustomerOrderCreationFlow { protected Customer customer; protected IOrderService orderService; protected Order order; [Given(@\u0026quot;a Customer\u0026quot;)\\] public void GivenACustomer() { customer = new Customer(); } [When(@\u0026quot;I create an order\u0026quot;)\\] public void WhenICreateAnOrder() { orderService = new OrderService(); order = orderService.Create(customer); } [When(@\u0026quot;the Customers name is Test Customer\u0026quot;)\\] public void WhenTheCustomersNameIsTestCustomer() { customer.FirstName = \u0026quot;Test\u0026quot;; customer.LastName = \u0026quot;Customer\u0026quot;; } [Then(@\u0026quot;a new order is created\u0026quot;)\\] public void ThenANewOrderIsCreated() { order.ShouldNotBeNull(\u0026quot;Order is null\u0026quot;); order.CurrentState.ShouldBeOfType(typeof (Created)); } Adding orders\nFeature: Manage an order As a user I want to change the customer order I add a product Then an order item is added to the order\n@AddSingleProduct Scenario: Add single product to an order Given A Customer with Name Joe Smith Given an order When I add a product Then an order item should be added\n@AddMultipleProducts Scenario: Add Multiple Products to an Order Given A Customer with Name Joe Smith Given an order When I add the following products | Id | Name | ProductType | Imported | Price | | 1 | A-Book | Book | True | 33.45 | | 2 | CD | Medical | false | 15.00 | | 3 | Chocolates | Food | true | 5.00 | | 4 | Gym Socks | Other | false | 3.00 | Then an order item should be added\nAnd the code:\n[Binding] public class OrderInProgressFlow { private Order order; private IOrderService orderService; private Customer customer; private Product product; private IList\u0026lt;Product\\\u0026gt; tableProducts; [Given(@\u0026quot;an order\u0026quot;)] public void GivenAnOrder() { var stubOrder = new Order() { Name = string.Format(\u0026quot;Order for {0} {1}\u0026quot;, customer.FirstName, customer.LastName), }; stubOrder.CurrentState = new Created(stubOrder); orderService = MockRepository.GenerateMock\u0026lt;IOrderService\\\u0026gt;(); orderService.Stub(a =\u0026gt; a.Create(customer)).Return(stubOrder); order = orderService.Create(customer); } [Given(@\u0026quot;A Customer with Name Joe Smith\u0026quot;)] public void GivenACustomerWithNameJoeSmith() { customer = new Customer {FirstName = \u0026quot;Joe\u0026quot;, LastName = \u0026quot;Smith\u0026quot;}; } [When(@\u0026quot;I add a product\u0026quot;)\\] public void WhenIAddAProduct() { product = new ProductBuilder() .WithId(1) .WithPrice(5) .WithName(\u0026quot;AAA\u0026quot;) .WithProductType(ProductType.Other) .Build(); order.AddProduct(product); } [Then(@\u0026quot;an order item should be added\u0026quot;)] public void ThenAnOrderItemShouldBeAdded() { if (product != null) { order.OrderItems.Any(a =\u0026gt; a.Product.Id == product.Id).ShouldBeTrue(); } else { tableProducts.Each(a =\u0026gt; order.OrderItems.Any(b =\u0026gt; b.Product.Id == a.Id).ShouldBeTrue()); } } [When(@\u0026quot;I add the following products\u0026quot;)] public void WhenIAddTheFollowingProducts(Table table) { tableProducts = new List\u0026lt;Product\\\u0026gt;(); SpecFlowHelpers.ConvertTableToProductList(table); tableProducts.Each(order.AddProduct); } And finally the big one – Order Completion\nFeature: Sales tax should be 10% for all goods except books food and medical products\nWhen an order is completed\nAs a user\nI want to calculate the sales taxes\n@CalculateSalesTax1 Scenario: Calculate Sales Tax\nGiven A Customer with Name Joe Smith\nGiven an order that is in progress\nWhen I add the following products to the inprogress order\nId Name ProductType Imported Price 1 A-Book Book false 12.49 2 Music CD Other false 14.99 3 Chocolates Food false 00.85 When the order is completed Then the sales tax should be 1.50 And the total should be 29.83 @CalculateSalesTax2 Scenario: Calculate Sales Tax for imported items\nGiven A Customer with Name Joe Smith\nGiven an order that is in progress\nWhen I add the following imported products to the inprogress order\nId Name ProductType Imported Price 1 Chocolates Food true 10.00 2 Perfume CD Other true 47.50 When the order is completed Then the sales tax should be 7.65 @CalculateSalesTax3 Scenario: Calculate Sales Tax for both types of items\nGiven A Customer with Name Joe Smith\nGiven an order that is in progress\nWhen I add the following imported products to the inprogress order\nId Name ProductType Imported Price 1 perfume Other true 27.99 2 perfume Other false 18.99 3 pills Medical false 9.75 4 chocolate Food true 11.25 When the order is completed\nThen the sales tax should be 6.70\nAnd the code:\nNote: Really this should be refactored into different re-usable steps and separate feature files – see this http://stackoverflow.com/questions/5228030/specflow-re-usable-step-definitions\n[Binding] public class OrderCompleteFlow { private Order order; private IOrderService orderService; private Customer customer; private IList\u0026lt;Product\\\u0026gt; tableProducts; [Given(@\u0026quot;an order thats in progress\u0026quot;)\\] public void GivenAnOrderThatsInProgress() { customer = MockRepository.GenerateStub\u0026lt;Customer\\\u0026gt;(); order = new Order() { Name = string.Format(\u0026quot;Order for {0} {1}\u0026quot;, customer.FirstName, customer.LastName), }; order.CurrentState = new Created(order); } [When(@\u0026quot;I add the following products to the inprogress order\u0026quot;)\\] public void WhenIAddTheFollowingProductsToTheInprogressOrder(Table table) { AddSpecFlowTableProductsToProductList(table); } private void AddSpecFlowTableProductsToProductList(Table table) { tableProducts = new List\u0026lt;Product\\\u0026gt;(); tableProducts = SpecFlowHelpers.ConvertTableToProductList(table); tableProducts.Each(order.AddProduct); } [When(@\u0026quot;I add the following imported products to the inprogress order\u0026quot;)\\] public void WhenIAddTheFollowingImportedProductsToTheInprogressOrder(Table table) { AddSpecFlowTableProductsToProductList(table); } [When(@\u0026quot;the order is completed\u0026quot;)\\] public void WhenTheOrderIsCompleted() { orderService = IocContainer.Instance.Resolve\u0026lt;IOrderService\\\u0026gt;(); orderService.Complete(order); } [Then(@\u0026quot;the sales tax should be 1\\\\.50\u0026quot;)\\] public void ThenTheSalesTaxShouldBe1\\_50() { order.TotalTax.ShouldEqual(1.5m); } [Then(@\u0026quot;the total should be 29\\\\.83\u0026quot;)\\] public void ThenTheTotalShouldBe29\\_83() { order.TotalOrderCost.ShouldEqual(29.83m); } [Then(@\u0026quot;the sales tax should be 7\\\\.65\u0026quot;)\\] public void ThenTheSalesTaxShouldBe7\\_65() { order.TotalTax.ShouldEqual(7.65m); } [Then(@\u0026quot;the sales tax should be 6\\\\.70\u0026quot;)\\] public void ThenTheSalesTaxShouldBe6\\_70() { order.TotalTax.ShouldEqual(6.70m); } } Download the code here\n","permalink":"https://blog.mckelt.com/articles/posts/sales-tax-calculator-using-specflow-the-state-pattern-and-chained-commands/","summary":"\u003cp\u003eUsing \u003ca href=\"http://www.specflow.org/\" target=\"_blank\"\u003eSpecFlow\u003c/a\u003e heres how I solved the following problem\u003c/p\u003e\n\u003ch5 id=\"problem--sales-taxes\"\u003ePROBLEM : SALES TAXES\u003c/h5\u003e\n\u003cblockquote\u003e\n\u003cp\u003eBasic sales tax is applicable at a rate of 10% on all goods, except books, food, and medical products that are exempt. Import duty is an additional sales tax applicable on all imported goods at a rate of 5%, with no exemptions._\u003c/p\u003e\n\u003cp\u003eWhen I purchase items I receive a receipt which lists the name of all the items and their price (including tax), finishing with the total cost of the items, and the total amounts of sales taxes paid. The rounding rules for sales tax are that for a tax rate of n%, a shelf price of p contains (np/100 rounded up to the nearest 0.05) amount of sales tax.\u003c/p\u003e","title":"Sales Tax Calculator using SpecFlow \u0026 The State Pattern And Chained Commands"},{"content":"Interview Process Pairing Interview This workbook is designed to help focus on the important aspects of the interview. Take as many or as few notes as you need to answer the following questions, and fill in the interview summary:\nDesign What design process did they use before /while building the solution? We are looking to identify the ability decompose the problem into a possible solution. What processes and or tooling did they use?\nDraw a comprehensive diagram and explained the solution on a white board including a rough architecture diagram. Architecture On a white-board, can the user draw the logical architecture or their solution? We want to assess their ability to communicate their solution using a diagram as well as what thought they put into it.\nWhy did they choose their technology stack? We want to assess why they choose the tools and frameworks they used. Are there better solutions? Can they explain a good level of details for their technology? Ideally they can advocate for their solution.\nExpect different levels of technical knowledge based on the position of the candidate.\nChoose a tech stack that he was familiar with (Angular, Azure Functions) that was aligned to the problem space.\nCode \u0026amp; Development Do they understand their own code? They’ll be writing against their own solution, so if they’re not able to, we can kill the interview immediately.\nHow productive are they? We shouldn’t expect them to solve everything in the hour, but we would have an expectation of where someone at their level should get.\nVery productive, made all of the requested changes. Are they comfortable in the development environment? Ideally we should ask them to use their own laptops so that they have the tools and setup they used to create the solution. We’re looking to see how mature they are in their use of tools, and would expect them to be pretty competent typing, using shortcuts etc.\nSuper comfortable / capable within Visual Studio Code. Learned a few new features watching him code. Team Work \u0026amp; Communication Are they willing/able to start writing code? We want to see a willingness to take on writing code in front of someone, even if they’ve never paired before.\nHow do they respond to feedback? If they’re too defensive or overly accepting we’d need to think of how this would work in a team.\nDo they make sure the person they’re working with understands what they’re doing? The pairing interviewer may not have seen their solution before, so we want to make sure they don’t just smash on and forget the person they’re pairing with.\nWe want to see how they interact and deal with other developers, and explain their work and thought process.\nOverall Is this someone I would want on my team? Is this person someone I could work with day-to day?\nYes, I think he has a good team fit as well as technical capability.\nWhat is the breadth and depth of the candidate’s technical knowledge? Ideally we want well rounded team members, with a core competency and complementary skills.\nSeems to have a good level of ASP.Net Core \u0026amp; mobility exposure. Has additional experience in Azure and Machine Learning.\nWhere are the gaps or boundaries in the candidate’s knowledge? What do they know well and where will they need to improve?\nPossibly on the technical architecture side of things based on his architecture diagram on the whiteboard.\n","permalink":"https://blog.mckelt.com/articles/posts/interview-process/","summary":"\u003ch1 id=\"interview-process\"\u003eInterview Process\u003c/h1\u003e\n\u003ch2 id=\"pairing-interview\"\u003ePairing Interview\u003c/h2\u003e\n\u003cp\u003eThis workbook is designed to help focus on the important aspects of the interview. Take as many or as few notes as you need to answer the following questions, and fill in the interview summary:\u003c/p\u003e\n\u003ch2 id=\"design\"\u003eDesign\u003c/h2\u003e\n\u003cp\u003eWhat design process did they use before /while building the solution?\nWe are looking to identify the ability decompose the problem into a possible solution. What processes and or tooling did they use?\u003c/p\u003e","title":"Interview Process"},{"content":" open System\n#light // Hello world let a = \u0026ldquo;Hello, world!\u0026rdquo;;\nlet mutable b = 0;\nwhile b \u0026lt; 10 do b \u0026lt;- b+1\nConsole.WriteLine(a + b.ToString())\nConsole.ReadLine() |\u0026gt; ignore\n// recursive binary search - http://rosettacode.org/wiki/Binary_search#F.23\nlet items = [| 10; 20; 30; 40; 50; 60; 70; 80; 90; 100; |]\nlet rec binarySearch (arr:int[], low:int, high:int, value:int) = if (high \u0026lt; low) then\nfalse\nelse\nlet mid = (low + high) / 2\nif (arr.\\[mid\\] \u0026gt; value) then binarySearch (arr, low, mid-1, value) else if (arr.\\[mid\\] \u0026lt; value) then binarySearch (arr, mid+1, high, value) else true let result = binarySearch (items, 0, 10, 80);\nlet any_to_string = sprintf \u0026ldquo;%A\u0026rdquo; printf \u0026ldquo;Binary Search found: %s\\n\u0026rdquo; (any_to_string result);\nConsole.ReadLine() |\u0026gt; ignore\n// run for one minute let time = DateTime.Now.AddHours(0.5).Ticks;\nlet mutable continueRunning = true\nlet dt = DateTime.Now.AddMinutes(1.0)\nwhile continueRunning do\nlet currentTime = System.DateTime.Now.ToString()\nConsole.WriteLine currentTime |\u0026gt; ignore\nif System.DateTime.Now.Ticks \u0026gt; dt.Ticks then continueRunning \u0026lt;- false\n","permalink":"https://blog.mckelt.com/articles/posts/f-beginnings/","summary":"\u003cblockquote\u003e\n\u003cp\u003eopen System\u003c/p\u003e\n\u003cp\u003e#light // Hello world let a = \u0026ldquo;Hello, world!\u0026rdquo;;\u003c/p\u003e\n\u003cp\u003elet mutable b = 0;\u003cbr\u003e\nwhile b \u0026lt; 10 do b \u0026lt;- b+1\u003cbr\u003e\nConsole.WriteLine(a + b.ToString())\u003c/p\u003e\n\u003cp\u003eConsole.ReadLine() |\u0026gt; ignore\u003c/p\u003e\n\u003cp\u003e// recursive binary search  - \u003ca href=\"http://rosettacode.org/wiki/Binary\" target=\"_blank\"\u003ehttp://rosettacode.org/wiki/Binary\u003c/a\u003e_search#F.23\u003cbr\u003e\nlet items = [| 10; 20; 30; 40; 50; 60; 70; 80; 90; 100; |]\u003c/p\u003e\n\u003cp\u003elet rec binarySearch (arr:int[], low:int, high:int, value:int) =\nif (high \u0026lt; low) then\u003cbr\u003e\nfalse\u003cbr\u003e\nelse\u003cbr\u003e\nlet mid = (low + high) / 2\u003c/p\u003e","title":"F# Beginnings"},{"content":" ","permalink":"https://blog.mckelt.com/articles/posts/f-keywords/","summary":"\u003cscript src=\"https://gist.github.com/chrismckelt/a6dc122913bdd40616a5.js\"\u003e\u003c/script\u003e","title":"DatabaseBackup.fs"},{"content":"A quick experiment with Spec Flow \u0026ndash; http://www.specflow.org/ Spec flow feature Feature: Run Specification rules To stop large postage costs As a user I want to be stopped from buying to much if I am in Australia\n@CountryAllowedToProcessOrderWithLargeCost Scenario: Orders of 20 cannot be sent to Australia\nGiven I have a customer with an order for socks And the order is to be sent to Australia When I process the order Then I should not be able to place the order Spec flow acceptance test namespace AcceptanceTests.StepDefinitions { [Binding] public class StepDefinitions { private Customer customer;\nprivate Order order; private Product product; private bool orderOk; [Given(@\u0026quot;I have a customer with an order for socks\u0026quot;)] public void GivenIHaveACustomerWithAnOrderForSocks() { customer = new Customer(){FirstName = \u0026quot;chris\u0026quot;, LastName = \u0026quot;mckelt\u0026quot;}; product = new SockProduct() {Id = 1, Name = \u0026quot;AAA\u0026quot;, Price = 30}; order = new Order(customer); order.AddProduct(product); } \\[Given(@\u0026quot;the order is to be sent to Australia\u0026quot;)\\] public void GivenTheOrderIsToBeSentToAustralia() { order.SetShippingDestination(ShippingDestination.Australia); } \\[Then(@\u0026quot;I should not be able to place the order\u0026quot;)\\] public void ThenIShouldNotBeAbleToPlaceTheOrder() { Assert.IsFalse(orderOk); } \\[When(@\u0026quot;I process the order\u0026quot;)\\] public void WhenIProcessTheOrder() { orderOk = order.CanBecome(new OrderConfirmed()); } } }\nThe state change from ‘order placed’ to ‘order confirmed’ is not allowed due to 2 specifications\npublic ISpecification\u0026lt;Order\u0026gt; CreateCanBecomeSpecification(IOrderState newState) { ISpecification\u0026lt;Order\u0026gt; spec = new CustomerNameCannotBeEmptySpecification(); spec = spec.And(new ShippingToAustraliaWithPriceOver20NotAllowedSpecification()); return spec; } Use Linq Update from the future - use LINQ!\n","permalink":"https://blog.mckelt.com/articles/posts/spec-flow-specifications-and-chained-commands/","summary":"\u003ch1 id=\"a-quick-experiment-with-spec-flow--httpwwwspecfloworg\"\u003eA quick experiment with Spec Flow \u0026ndash; \u003ca href=\"http://www.specflow.org/\" title=\"http://www.specflow.org/\" target=\"_blank\"\u003ehttp://www.specflow.org/\u003c/a\u003e\u003c/h1\u003e\n\u003ch2 id=\"spec-flow-feature\"\u003eSpec flow feature\u003c/h2\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eFeature: Run Specification rules\nTo stop large postage costs\nAs a user\nI want to be stopped from buying to much if I am in Australia\u003c/p\u003e\n\u003cp\u003e@CountryAllowedToProcessOrderWithLargeCost Scenario: Orders of 20 cannot be sent to Australia\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eGiven I have a customer with an order for socks\nAnd the order is to be sent to Australia\nWhen I process the order\nThen I should not be able to place the order\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e \u003c/p\u003e","title":"Spec Flow, Specifications and Chained Commands"},{"content":"XP\n5 values 14 principles 12 Primary practices 11 Corollary practices Lean\n7 principles 22 thinking tools Scrum\n5 Values 3 Roles (Product owner, scrum master, scrum team) 3 Ceremonies (Sprint planning meeting, Stand up, review \u0026amp; retrospective) 3 Work Products (product backlog, sprint backlog, burndown chart) (depending on which definition you choose) DSDM Atern\n8 Principles 5 Lifecycle phases 12 roles 17 work products 5 key techniques Agile Unified Process\n6 Principles 7 Disciplines 4 Lifecycle Phases 14 Roles 8 minimum deliverables 4 guidance pieces ","permalink":"https://blog.mckelt.com/articles/posts/agile-flavours/","summary":"\u003cp\u003e\u003cstrong\u003eXP\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e5 values\u003c/li\u003e\n\u003cli\u003e14 principles\u003c/li\u003e\n\u003cli\u003e12 Primary practices\u003c/li\u003e\n\u003cli\u003e11 Corollary practices\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eLean\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e7 principles\u003c/li\u003e\n\u003cli\u003e22 thinking tools\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eScrum\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e5 Values\u003c/li\u003e\n\u003cli\u003e3 Roles (Product owner, scrum master, scrum team)\u003c/li\u003e\n\u003cli\u003e3 Ceremonies  (Sprint planning meeting, Stand up, review \u0026amp; retrospective)\u003c/li\u003e\n\u003cli\u003e3 Work Products (product backlog, sprint backlog, burndown chart)\u003c/li\u003e\n\u003cli\u003e(depending on which definition you choose)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eDSDM Atern\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e8 Principles\u003c/li\u003e\n\u003cli\u003e5 Lifecycle phases\u003c/li\u003e\n\u003cli\u003e12 roles\u003c/li\u003e\n\u003cli\u003e17 work products\u003c/li\u003e\n\u003cli\u003e5 key techniques\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eAgile Unified Process\u003c/strong\u003e\u003c/p\u003e","title":"Agile Flavours"},{"content":"How to use a custom NHibernate User Type To store the state of a Risk (ie RiskState) as a value in a column we can use a NHibernate.UserType\nThe RiskState can be one of the following: (these are all derived from RiskState which implements IRiskState)\nOur user type\npublic class RiskStateNameUserType: IUserType { #region IUserType Members public object Assemble(object cached, object owner) { return cached; } public object DeepCopy(object value) { return value; } public object Disassemble(object value) { return value; } public int GetHashCode(object x) { return x.GetHashCode(); } public bool IsMutable { get { return false; } } public object NullSafeGet(System.Data.IDataReader dr, string\\[\\] names, object owner) { var property0 = NHibernateUtil.String.NullSafeGet(dr, names\\[0\\]); if (property0 == null) { return null; } IRiskState state; if (owner is Risk) { state = (IRiskState) Activator.CreateInstance(Type.GetType(typeof (IRiskState).Namespace + \u0026quot;.\u0026quot; + (string) property0), owner); } else { state = (IRiskState) Activator.CreateInstance(Type.GetType(typeof (IRiskState).Namespace + \u0026quot;.\u0026quot; + (string) property0)); } return state; } public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index) { if (value == null) { ((IDataParameter) cmd.Parameters\\[index\\]).Value = DBNull.Value; } else { var state = (IRiskState) value; ((IDataParameter) cmd.Parameters\\[index\\]).Value = state.GetType().Name; } } public object Replace(object original, object target, object owner) { return original; } public Type ReturnedType { get { return typeof (RiskState); } } public NHibernate.SqlTypes.SqlType\\[\\] SqlTypes { get { return new\\ [\\] { NHibernateUtil.String.SqlType }; } } public new bool Equals(object x, object y) { if (x == null \u0026amp;\u0026amp; y == null) return true; if (x == null || y == null) return false; return x.GetType() == y.GetType(); } #endregion } Using this on a property as follows:\n[Property(ColumnType = \u0026quot;Demo.Core.Risks.RiskStateNameUserType, Demo.Core\u0026quot;)] public IRiskState RequiredState { get; set; } We can now store types:\nIf importing from a file and we want to parse a string to our user type\nprotected T GetCustomType\u0026lt;T\u0026gt;(XElement dsl, string attributeName) { string attribute = (string)dsl.Attribute(attributeName); var customType = (T)Activator.CreateInstance(Type.GetType(typeof(T).Namespace + \u0026quot;.\u0026quot; + attribute)); return customType; } ","permalink":"https://blog.mckelt.com/articles/posts/custom-nhibernate-user-type-2/","summary":"\u003ch1 id=\"how-to-use-a-custom-nhibernate-user-type\"\u003eHow to use a custom NHibernate User Type\u003c/h1\u003e\n\u003cp\u003eTo store the state of a Risk (ie RiskState) as a value in a column we can use a NHibernate.UserType\u003c/p\u003e\n\u003cp\u003eThe RiskState can be one of the following: (these are all derived from RiskState which implements IRiskState)\u003c/p\u003e\n\u003cp\u003eOur user type\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e public class RiskStateNameUserType: IUserType {\n  #region IUserType Members\n  public object Assemble(object cached, object owner)  \n {\n    return cached;\n}\n public object DeepCopy(object value)\n{\n  return value;\n}\npublic object Disassemble(object value)\n{\n  return value;\n}\n  public int GetHashCode(object x)\n{\n  return x.GetHashCode();\n}\npublic bool IsMutable\n{\nget {\n  return false;\n}\n  }\n  public object NullSafeGet(System.Data.IDataReader dr, string\\[\\] names, object owner)  \n{  \nvar property0 = NHibernateUtil.String.NullSafeGet(dr, names\\[0\\]);\n\nif (property0 == null)\n{\n  return null;\n}\nIRiskState state;\nif (owner is Risk)\n{\n  state =\n    (IRiskState)\n  Activator.CreateInstance(Type.GetType(typeof (IRiskState).Namespace + \u0026quot;.\u0026quot; + (string) property0),\n    owner);\n} else\n{\n  state =\n    (IRiskState)\n  Activator.CreateInstance(Type.GetType(typeof (IRiskState).Namespace + \u0026quot;.\u0026quot; + (string) property0));\n}\nreturn state; \n  }   \n  public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)\n {\n   if (value == null)\n{\n    ((IDataParameter) cmd.Parameters\\[index\\]).Value = DBNull.Value;\n   } else\n  {\n    var state = (IRiskState) value;\n  ((IDataParameter) cmd.Parameters\\[index\\]).Value = state.GetType().Name;\n  }\n}\n  public object Replace(object original,  object target, object owner)\n{\n    return original;\n    }\n    public Type ReturnedType\n  {\n    get {\n      return typeof (RiskState);\n    }\n}\npublic NHibernate.SqlTypes.SqlType\\[\\] SqlTypes\n{\n  get {\n    return new\\ [\\] {\n      NHibernateUtil.String.SqlType\n    };\n    }\n  }\n  public new bool Equals(object x, object y)\n{\n  if (x == null \u0026amp;\u0026amp; y == null) return true;\n  if (x == null || y == null) return false;\n  return x.GetType() == y.GetType();\n}\n#endregion\n  }\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eUsing this on a property as follows:\u003c/p\u003e","title":"Custom NHibernate User Type"},{"content":"\u0026ldquo;Invalid object name \u0026lsquo;master.dbo.spt_values\u0026rsquo;.\u0026rdquo; This means your SQL Master DB is in a bad state.\nTo fix:\nError- Invalid object name \u0026lsquo;master.dbo.spt_values\u0026rsquo;.\nCD\n\u0026ldquo;C:\\Program Files\\Microsoft SQL Server\\MSSQL10.MSSQLSERVER\\MSSQL\\Install\u0026rdquo;\nrun u_tables.sql in master\u0026hellip;.\n","permalink":"https://blog.mckelt.com/articles/posts/invalid-object-name-master-dbo-spt-values/","summary":"\u003ch1 id=\"invalid-object-name-masterdbospt_values\"\u003e\u0026ldquo;Invalid object name \u0026lsquo;master.dbo.spt_values\u0026rsquo;.\u0026rdquo;\u003c/h1\u003e\n\u003cp\u003eThis means your SQL Master DB is in a bad state.\u003c/p\u003e\n\u003cp\u003eTo fix:\u003c/p\u003e\n\u003cp\u003eError- Invalid object name \u0026lsquo;master.dbo.spt_values\u0026rsquo;.\u003c/p\u003e\n\u003cp\u003eCD\u003c/p\u003e\n\u003cp\u003e\u0026ldquo;C:\\Program Files\\Microsoft SQL Server\\MSSQL10.MSSQLSERVER\\MSSQL\\Install\u0026rdquo;\u003c/p\u003e\n\u003cp\u003erun \u003cstrong\u003eu_tables.sql\u003c/strong\u003e in master\u0026hellip;.\u003c/p\u003e","title":"Invalid object name 'master.dbo.spt_values'."},{"content":"The following test would fail without this\n.WhenCalled(invocation =\u0026gt; invocation.ReturnValue = new TestResult(){IsTrue = true, Message = \u0026quot;BBB\u0026quot;}) [TestClass] public class ChrisTest { private IRuleService ruleService; [TestMethod] public void ShouldNotChangeReturnedTestResult() { ruleService = MockRepository.GenerateMock\u0026lt;IRuleService\u0026gt;(); var testResult = new TestResult(); testResult.IsTrue = true; testResult.Message = \u0026quot;AAA\u0026quot;; ruleService.Stub(a =\u0026gt; a.GetTestResult()).Return(testResult) .WhenCalled(invocation =\u0026gt; invocation.ReturnValue = new TestResult(){IsTrue = true, Message = \u0026quot;BBB\u0026quot;}); var testClass = new TestClass(ruleService); testClass.KillTheString(); Assert.IsTrue(testClass.StringIsThere()); } public interface IRuleService { TestResult GetTestResult(); } public class TestResult { public bool IsTrue { get; set; } public string Message { get; set; } } private class TestClass { private readonly IRuleService ruleService; public TestClass(IRuleService ruleService) { this.ruleService = ruleService; } public void KillTheString() { var result = ruleService.GetTestResult(); result.Message = string.Empty; } public bool StringIsThere() { var result = ruleService.GetTestResult(); return !string.IsNullOrEmpty(result.Message); } } } ","permalink":"https://blog.mckelt.com/articles/posts/rhinomocks-whencalled/","summary":"\u003cp\u003eThe following test would fail without this\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e.WhenCalled(invocation =\u0026gt; invocation.ReturnValue = new TestResult(){IsTrue = true, Message = \u0026quot;BBB\u0026quot;})\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e[TestClass]\npublic class ChrisTest\n{\n    private IRuleService ruleService;\n\n   [TestMethod]\n    public void ShouldNotChangeReturnedTestResult()\n    {\n        ruleService = MockRepository.GenerateMock\u0026lt;IRuleService\u0026gt;();\n        var testResult = new TestResult();\n        testResult.IsTrue = true;\n        testResult.Message = \u0026quot;AAA\u0026quot;;\n        ruleService.Stub(a =\u0026gt; a.GetTestResult()).Return(testResult)\n            .WhenCalled(invocation =\u0026gt; invocation.ReturnValue = new TestResult(){IsTrue = true, Message = \u0026quot;BBB\u0026quot;});\n\n        var testClass = new TestClass(ruleService);\n        testClass.KillTheString();\n        Assert.IsTrue(testClass.StringIsThere());\n        \n    }\n\n    public interface IRuleService\n    {\n        TestResult GetTestResult();\n    }\n\n    public class TestResult\n    {\n        public bool IsTrue { get; set; }\n        public string Message { get; set; }\n    }\n\n    private class TestClass\n    {\n        private readonly IRuleService ruleService;\n\n        public TestClass(IRuleService ruleService)\n        {\n            this.ruleService = ruleService;\n        }\n\n        public void KillTheString()\n        {\n            var result = ruleService.GetTestResult();\n            result.Message = string.Empty;\n        }\n\n        public bool StringIsThere()\n        {\n            var result = ruleService.GetTestResult();\n            return !string.IsNullOrEmpty(result.Message);\n        }\n    }\n}\n\u003c/code\u003e\u003c/pre\u003e","title":"RhinoMocks – WhenCalled"},{"content":"Crystal Software Development Download Agile talk\n","permalink":"https://blog.mckelt.com/articles/posts/crystal-software-development-2/","summary":"\u003ch1 id=\"crystal-software-development-download\"\u003eCrystal Software Development \u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2010/06/Crystal.pptx\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide1.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide1\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide1_thumb.png\" title=\"Slide1\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide2.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide2\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide2_thumb.png\" title=\"Slide2\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide3.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide3\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide3_thumb.png\" title=\"Slide3\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide4.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide4\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide4_thumb.png\" title=\"Slide4\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide5.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide5\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide5_thumb.png\" title=\"Slide5\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide6.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide6\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide6_thumb.png\" title=\"Slide6\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide7.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide7\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide7_thumb.png\" title=\"Slide7\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide8.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide8\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide8_thumb.png\" title=\"Slide8\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide9.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide9\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide9_thumb.png\" title=\"Slide9\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide10.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide10\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide10_thumb.png\" title=\"Slide10\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide11.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide11\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide11_thumb.png\" title=\"Slide11\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide12.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide12\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide12_thumb.png\" title=\"Slide12\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide13.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide13\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide13_thumb.png\" title=\"Slide13\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide14.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide14\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide14_thumb.png\" title=\"Slide14\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide15.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide15\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide15_thumb.png\" title=\"Slide15\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide16.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide16\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide16_thumb.png\" title=\"Slide16\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide17.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide17\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide17_thumb.png\" title=\"Slide17\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide18.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide18\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide18_thumb.png\" title=\"Slide18\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide19.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide19\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide19_thumb.png\" title=\"Slide19\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide20.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide20\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide20_thumb.png\" title=\"Slide20\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide21.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide21\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide21_thumb.png\" title=\"Slide21\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide22.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide22\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide22_thumb.png\" title=\"Slide22\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide23.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide23\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide23_thumb.png\" title=\"Slide23\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide24.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide24\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide24_thumb.png\" title=\"Slide24\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide25.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide25\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide25_thumb.png\" title=\"Slide25\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide26.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide26\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide26_thumb.png\" title=\"Slide26\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide27.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide27\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide27_thumb.png\" title=\"Slide27\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide28.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide28\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide28_thumb.png\" title=\"Slide28\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide29.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide29\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide29_thumb.png\" title=\"Slide29\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide30.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide30\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide30_thumb.png\" title=\"Slide30\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide31.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide31\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide31_thumb.png\" title=\"Slide31\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide32.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide32\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide32_thumb.png\" title=\"Slide32\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide33.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide33\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide33_thumb.png\" title=\"Slide33\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide34.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide34\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide34_thumb.png\" title=\"Slide34\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide35.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide35\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide35_thumb.png\" title=\"Slide35\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide36.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide36\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide36_thumb.png\" title=\"Slide36\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide37.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide37\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide37_thumb.png\" title=\"Slide37\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide38.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide38\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide38_thumb.png\" title=\"Slide38\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide39.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide39\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide39_thumb.png\" title=\"Slide39\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide40.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide40\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide40_thumb.png\" title=\"Slide40\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide41.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide41\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide41_thumb.png\" title=\"Slide41\"\u003e\u003c/a\u003e\u003ca href=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/2018/08/Slide42.png\" target=\"_blank\"\u003e\u003cimg alt=\"Slide42\" loading=\"lazy\" src=\"https://raw.githubusercontent.com/chrismckelt/chrismckelt.github.io/master/_posts/posts/images/Slide42_thumb.png\" title=\"Slide42\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eAgile talk\u003c/p\u003e","title":"Crystal Software Development"},{"content":"Using Integrated Security in connection strings should be either of the following:\nIntegrated Security=SSPI or\nIntegrated Security=false Not\nIntegrated Security=true ","permalink":"https://blog.mckelt.com/articles/posts/integrated-security-sspi-security-support-provider-interface/","summary":"\u003cp\u003eUsing Integrated Security in connection strings should be either of the following:\u003c/p\u003e\n\u003ch3 id=\"integrated-securitysspi\"\u003eIntegrated Security=SSPI\u003c/h3\u003e\n\u003cp\u003eor\u003c/p\u003e\n\u003ch3 id=\"integrated-securityfalse\"\u003eIntegrated Security=false\u003c/h3\u003e\n\u003cp\u003eNot\u003c/p\u003e\n\u003ch5 id=\"integrated-securitytrue\"\u003e\u003cdel\u003eIntegrated Security=true\u003c/del\u003e\u003c/h5\u003e","title":"Integrated Security = SSPI -- Security Support Provider Interface"},{"content":" LIFO FIFO higher COGS lower COGS lower taxes higher taxes lower net income higher net income lower inventory balances higher inventory balances higher cash flows (less tax paid out) lower cash flows (more tax paid out) lower net and gross margins higher net and gross margins lower current ratio higher current ratio higher inventory turnover lower inventory turnover DA and DE higher DA and DE lower Under IFRS the permissible cost flow methods are:\nSpecific Identification FIFO Weighted average cost ","permalink":"https://blog.mckelt.com/articles/posts/lifo-vs-fifo/","summary":"\u003ctable id=\"tbl1\"\u003e\n    \u003cthead\u003e\n    \u003ctr\u003e\n            \u003cth valign=\"top\" width=\"255\"\u003eLIFO\u003c/th\u003e\n            \u003cth valign=\"top\" width=\"57\"\u003e\u003c/th\u003e\n            \u003cth valign=\"top\" width=\"288\"\u003eFIFO\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003ehigher COGS\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003elower COGS\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003elower taxes\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003ehigher taxes\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003elower net income\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003ehigher net income\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003elower inventory balances\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003ehigher inventory balances\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003ehigher cash flows (less tax paid out)\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003elower cash flows (more tax paid out)\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003elower net and gross margins\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003ehigher net and gross margins\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003elower current ratio\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003ehigher current ratio\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003ehigher inventory turnover\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003elower inventory turnover\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd valign=\"top\" width=\"255\"\u003eDA and DE higher\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"57\"\u003e\u003c/td\u003e\n            \u003ctd valign=\"top\" width=\"288\"\u003eDA and DE lower\u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cp\u003eUnder IFRS the permissible cost flow methods are:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSpecific Identification\u003c/li\u003e\n\u003cli\u003eFIFO\u003c/li\u003e\n\u003cli\u003eWeighted average cost\u003c/li\u003e\n\u003c/ul\u003e","title":"LIFO vs FIFO"},{"content":"A simple implemention for calling asych methods from the UI Examples dispatcher.ExecuteOnMainUIThread(CommandManager.InvalidateRequerySuggested); dispatcher.Execute(() =\u0026gt; { SomeLongRunningMethodHere(); }); The interface public interface IDispatcher { void Execute(Action action); void ExecuteOnMainUIThread(Action action); } }\nSynchronous for use in Testing public class SynchronousDispatcher: IDispatcher { public void Execute(Action action) { action(); } public void ExecuteOnMainUIThread(Action action) { action(); } }\nAsynchronous for use by the application at run time public class AsynchronousDispatcher: IDispatcher { public void Execute(Action action) { action.BeginInvoke(CallBack, action); } public void ExecuteOnMainUIThread(Action action) { Dispatcher dispatcher; if (Application.Current != null) { dispatcher = Application.Current.Dispatcher; } else { dispatcher = Dispatcher.CurrentDispatcher; } dispatcher.Invoke(action); } private void CallBack(IAsyncResult result) { try { ((Action) result.AsyncState).EndInvoke(result); } catch (Exception ex) { // Need to raise the exception on the main thread ExecuteOnMainUIThread(() =\u0026gt; { throw ex; } ); } finally { result.AsyncWaitHandle.Close(); } } } ","permalink":"https://blog.mckelt.com/articles/posts/wpf-ui-thread-dispatcher/","summary":"\u003ch2 id=\"a-simple-implemention-for-calling-asych-methods-from-the-ui\"\u003eA simple implemention for calling asych methods from the UI\u003c/h2\u003e\n\u003ch4 id=\"examples\"\u003eExamples\u003c/h4\u003e\n\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003e dispatcher.ExecuteOnMainUIThread(CommandManager.InvalidateRequerySuggested);\ndispatcher.Execute(() =\u0026gt;\n                                    {\n                                       SomeLongRunningMethodHere();\n                                    });\n\u003c/code\u003e\u003c/pre\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"the-interface\"\u003eThe interface\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003epublic interface IDispatcher\n{\nvoid Execute(Action action);\nvoid ExecuteOnMainUIThread(Action action);\n}\n}\u003c/p\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"synchronous-for-use-in-testing\"\u003eSynchronous for use in Testing\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003e public class SynchronousDispatcher: IDispatcher {  \n   public void Execute(Action action) {  \n  action();  \n}  \n\npublic void ExecuteOnMainUIThread(Action action) {\n  action();\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e}\u003c/p\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"asynchronous-for-use-by-the-application-at-run-time\"\u003eAsynchronous for use by the application at run time\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003epublic class AsynchronousDispatcher: IDispatcher {\npublic void Execute(Action action) {\n  action.BeginInvoke(CallBack, action);\n}\n\npublic void ExecuteOnMainUIThread(Action action) {\n  Dispatcher dispatcher;\n\n  if (Application.Current != null) {\n    dispatcher = Application.Current.Dispatcher;\n  } else {\n    dispatcher = Dispatcher.CurrentDispatcher;\n  }\n\n  dispatcher.Invoke(action);\n}\n\nprivate void CallBack(IAsyncResult result) {\n  try {\n    ((Action) result.AsyncState).EndInvoke(result);\n  } catch (Exception ex) { // Need to raise the exception on the main thread ExecuteOnMainUIThread(() =\u0026gt; { throw ex; } ); } finally { result.AsyncWaitHandle.Close(); }\n\n  }\n}\n\u003c/code\u003e\u003c/pre\u003e\u003c/blockquote\u003e","title":"WPF UI Thread Dispatcher"},{"content":"Rhino Mock Constraints allow use to test a methods parameters were called with the correct arguments.\npublic interface IDocumentService { void Save(string userName, Document document, Stream stream); }\nSome ways to ensure the method that contains the save method passes the correct internally constructed arguments include\ndocumentService.AssertWasCalled(a=\u0026gt;a.Save(\u0026ldquo;chris\u0026rdquo;, doc, adaptor.InputStream), b =\u0026gt; b.Constraints(Is.Equal(“chris”), Is.NotNull(), Is.AnyThing()));\nPassing in\nProperty.AllPropertiesMatch(this.MyTestObjectWithPropertiesThatShouldMatch) will check values against each object\n","permalink":"https://blog.mckelt.com/articles/posts/rhino-mock-constraints-assertwascalled/","summary":"\u003cp\u003eRhino Mock Constraints allow use to test a methods parameters were called with the correct arguments.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003epublic interface IDocumentService\n{\nvoid Save(string userName, Document document, Stream stream);\n}\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003eSome ways to ensure the method that contains the save method passes the correct internally constructed arguments include\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003edocumentService.AssertWasCalled(a=\u0026gt;a.Save(\u0026ldquo;chris\u0026rdquo;, doc, adaptor.InputStream), b =\u0026gt; b.Constraints(Is.Equal(“chris”), Is.NotNull(), Is.AnyThing()));\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003ePassing in\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eProperty.AllPropertiesMatch(this.MyTestObjectWithPropertiesThatShouldMatch)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003ewill check values against each object\u003c/p\u003e","title":"Rhino Mock Constraints  -- AssertWasCalled"},{"content":"Liquidity ratios $$\\text{Current ratio} = \\frac{\\text{Current Assets}}{\\text{Current Liabilities}}$$\n$$\\text{Quick (Acid Test) Ratio} = \\frac{\\text{Cash and Cash Equivalent} + \\text{Marketable Securities} + \\text{Accounts Receivable}}{\\text{Current Liabilities}}$$\nCash ratio is the same as Quick without the accounts receivable\nSolvency ratios Long term debt to equity = total debt / total equity\nDebt to equity = total debt / total equity\nTotal debt ratio = total debt / total assets\nFinancial leverage ratio = total assets / total equity\n","permalink":"https://blog.mckelt.com/articles/posts/cfa-accounting-ratios/","summary":"\u003ch1 id=\"liquidity-ratios\"\u003eLiquidity ratios\u003c/h1\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cp\u003e$$\\text{Current ratio} = \\frac{\\text{Current Assets}}{\\text{Current Liabilities}}$$\u003c/p\u003e\n\u003cp\u003e$$\\text{Quick (Acid Test) Ratio} = \\frac{\\text{Cash and Cash Equivalent} + \\text{Marketable Securities} + \\text{Accounts Receivable}}{\\text{Current Liabilities}}$$\u003c/p\u003e\n\u003cp\u003eCash ratio is the same as Quick without the accounts receivable\u003c/p\u003e\n\u003ch1 id=\"solvency-ratios\"\u003eSolvency ratios\u003c/h1\u003e\n\u003cp\u003eLong term debt to equity =  total debt / total equity\u003c/p\u003e\n\u003cp\u003eDebt to equity = total debt / total equity\u003c/p\u003e\n\u003cp\u003eTotal debt ratio = total debt / total assets\u003c/p\u003e\n\u003cp\u003eFinancial leverage ratio = total assets / total equity\u003c/p\u003e","title":"CFA – Accounting Ratios"},{"content":"In the following file C:\\\\Windows\\\\System32\\\\inetsrv\\\\config\\\\applicationHost.config Ensure the following\n\u0026lt;section name\\=\u0026quot;requestFiltering\u0026quot; overrideModeDefault\\=\u0026quot;Allow\u0026quot; /\u0026gt; In the Web.Config \u0026lt;?xml version\\=\u0026quot;1.0\u0026quot; encoding\\=\u0026quot;UTF-8\u0026quot;?\\\u0026gt; \u0026lt;configuration\u0026gt;\n\u0026lt;system.webServer\u0026gt;\n\u0026lt;handlers\u0026gt;\n\u0026lt;add name=\u0026ldquo;StaticFile\u0026rdquo; path=\u0026quot;*\u0026quot; verb=\u0026quot;*\u0026quot; modules=\u0026ldquo;StaticFileModule,DefaultDocumentModule,DirectoryListingModule\u0026rdquo; resourceType=\u0026ldquo;Either\u0026rdquo; requireAccess=\u0026ldquo;Read\u0026rdquo; /\u0026gt;\n\u0026lt;/handlers\u0026gt; \u0026lt;staticContent\u0026gt;\n\u0026lt;mimeMap fileExtension=\u0026quot;.*\u0026quot; mimeType=\u0026ldquo;application/octet-stream\u0026rdquo; /\u0026gt;\n\u0026lt;/staticContent\u0026gt;\n\u0026lt;security\u0026gt;\n\u0026lt;requestFiltering\u0026gt;\n\u0026lt;fileExtensions allowUnlisted=\u0026ldquo;true\u0026rdquo;\u0026gt;\n\u0026lt;remove fileExtension=\u0026quot;.config\u0026quot; /\u0026gt;\n\u0026lt;add fileExtension=\u0026quot;.config\u0026quot; allowed=\u0026ldquo;true\u0026rdquo; /\u0026gt;\n\u0026lt;/fileExtensions\u0026gt;\n\u0026lt;/requestFiltering\u0026gt;\n\u0026lt;/security\u0026gt;\n\u0026lt;/system.webServer\u0026gt;\n\u0026lt;/configuration\u0026gt;\n","permalink":"https://blog.mckelt.com/articles/posts/allow-iis7-to-download-config-files/","summary":"\u003ch3 id=\"in-the-following-file\"\u003eIn the following file\u003c/h3\u003e\n\u003cpre\u003e\u003ccode\u003eC:\\\\Windows\\\\System32\\\\inetsrv\\\\config\\\\applicationHost.config\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eEnsure the following\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026lt;section name\\=\u0026quot;requestFiltering\u0026quot; overrideModeDefault\\=\u0026quot;Allow\u0026quot; /\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"in-the-webconfig\"\u003eIn the Web.Config\u003c/h3\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026lt;?xml version\\=\u0026quot;1.0\u0026quot; encoding\\=\u0026quot;UTF-8\u0026quot;?\\\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u0026lt;configuration\u0026gt;\u003cbr\u003e\n\u0026lt;system.webServer\u0026gt;\u003cbr\u003e\n\u0026lt;handlers\u0026gt;\u003cbr\u003e\n\u003cclear /\u003e\u003cbr\u003e\n\u0026lt;add\nname=\u0026ldquo;StaticFile\u0026rdquo;\npath=\u0026quot;*\u0026quot; verb=\u0026quot;*\u0026quot;\nmodules=\u0026ldquo;StaticFileModule,DefaultDocumentModule,DirectoryListingModule\u0026rdquo;\nresourceType=\u0026ldquo;Either\u0026rdquo;\nrequireAccess=\u0026ldquo;Read\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;/handlers\u0026gt;\n\u0026lt;staticContent\u0026gt;\u003cbr\u003e\n\u0026lt;mimeMap fileExtension=\u0026quot;.*\u0026quot; mimeType=\u0026ldquo;application/octet-stream\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;/staticContent\u0026gt;\u003cbr\u003e\n\u0026lt;security\u0026gt;\u003cbr\u003e\n\u0026lt;requestFiltering\u0026gt;\u003cbr\u003e\n\u0026lt;fileExtensions allowUnlisted=\u0026ldquo;true\u0026rdquo;\u0026gt;\u003cbr\u003e\n\u0026lt;remove fileExtension=\u0026quot;.config\u0026quot; /\u0026gt;\u003cbr\u003e\n\u0026lt;add fileExtension=\u0026quot;.config\u0026quot; allowed=\u0026ldquo;true\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;/fileExtensions\u0026gt;\u003cbr\u003e\n\u0026lt;/requestFiltering\u0026gt;\u003cbr\u003e\n\u0026lt;/security\u0026gt;\u003cbr\u003e\n\u0026lt;/system.webServer\u0026gt;\u003cbr\u003e\n\u0026lt;/configuration\u0026gt;\u003c/p\u003e\u003c/blockquote\u003e","title":"Allow IIS7 to download .config files"},{"content":"using(var stream = Assembly.GetAssembly(typeof (StubPolicy)).GetManifestResourceStream( \u0026#34;Documents.TestHelpers.Files.test.msg\u0026#34;)) { const int bufferLength = 256; var buffer = new Byte\\[bufferLength\\]; if (stream != null) { int bytesRead = stream.Read(buffer, 0, bufferLength); using(var fs = new FileStream(filename, FileMode.CreateNew, FileAccess.Write)) { // Write out the input stream while (bytesRead \u0026gt; 0) { fs.Write(buffer, 0, bytesRead); bytesRead = stream.Read(buffer, 0, bufferLength); } fs.Close(); } stream.Close(); } } ","permalink":"https://blog.mckelt.com/articles/posts/stream-bytes-to-files/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing(\u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e stream =\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Assembly.GetAssembly(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (StubPolicy)).GetManifestResourceStream(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a50\"\u003e\u0026#34;Documents.TestHelpers.Files.test.msg\u0026#34;\u003c/span\u003e)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#00a\"\u003econst\u003c/span\u003e int bufferLength = \u003cspan style=\"color:#099\"\u003e256\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e buffer = new Byte\\[bufferLength\\];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (stream != null) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    int bytesRead = stream.Read(buffer, \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, bufferLength);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    using(\u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e fs = new FileStream(filename, FileMode.CreateNew, FileAccess.Write)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      // Write out the input stream\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#00a\"\u003ewhile\u003c/span\u003e (bytesRead \u0026gt; \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        fs.Write(buffer, \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, bytesRead);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        bytesRead = stream.Read(buffer, \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, bufferLength);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      fs.Close();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    stream.Close();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Stream bytes to files"},{"content":" public interface ISpecification\u0026lt;T\u0026gt; { bool IsSatisfiedBy(T candidate); ISpecification\u0026lt;T\u0026gt; And(ISpecification\u0026lt;T\u0026gt; other); ISpecification\u0026lt;T\u0026gt; Or(ISpecification\u0026lt;T\u0026gt; other); ISpecification\u0026lt;T\u0026gt; XOr(ISpecification\u0026lt;T\u0026gt; other); ISpecification\u0026lt;T\u0026gt; AndAllOf(IEnumerable\u0026lt;ISpecification\u0026lt;T\u0026gt;\u0026gt; specifications); T Target { get; set; } void GetResults(ResultsVisitor visitor); IEnumerable\u0026lt;Type\u0026gt; WhatWasAssessed(); Risks.IDemoCommand GetCommand(); } using System; using System.Collections.Generic; using Demo.Core.Commands; using Demo.Core.Risks; using Demo.Core.Specification.Common; namespace Demo.Core.Specification { public abstract class AbstractSpecification\u0026lt;T\u0026gt; : ISpecification\u0026lt;T\u0026gt; { protected SpecificationResult result; protected IList\u0026lt;Type\u0026gt; ruleList = new List\u0026lt;Type\u0026gt;(); protected bool SoftCheck { get; set; } public T Candidate { get; set; } public T Target { get; set; } public bool IsReplay {protected get; set;} public ISpecification\u0026lt;T\u0026gt; And(ISpecification\u0026lt;T\u0026gt; other) { return new AndSpecification\u0026lt;T\u0026gt;(this, other); } public ISpecification\u0026lt;T\u0026gt; Or(ISpecification\u0026lt;T\u0026gt; other) { return new OrSpecification\u0026lt;T\u0026gt;(this, other); } public ISpecification\u0026lt;T\u0026gt; XOr(ISpecification\u0026lt;T\u0026gt; other) { return new XORSpecification\u0026lt;T\u0026gt;(this, other); } public ISpecification\u0026lt;T\u0026gt; AndAllOf(IEnumerable\u0026lt;ISpecification\u0026lt;T\u0026gt;\u0026gt; specifications) { return new AndAllOfSpecification\u0026lt;T\u0026gt;(this, specifications); } public virtual bool Evaluate(T candidate) { throw new NotImplementedException(\u0026#34;You need to provide a predicate or override IsSatisfiedBy\u0026#34;); } public virtual IDemoCommand GetCommand() { return new NoCommand(); } public virtual void GetResults(ResultsVisitor visitor) { if (result != null \u0026amp;\u0026amp; !string.IsNullOrEmpty(result.Message)) { visitor.Add(result); } } public virtual IEnumerable\u0026lt;Type\u0026gt; WhatWasAssessed() { return ruleList; } public virtual string MessageFormat() { throw new NotImplementedException(\u0026#34;You need to provide a result a message or override IsSatisfiedBy\u0026#34;); } public virtual bool IsSatisfiedBy(T candidate) { if (IsReplay) { return true; } Type ruleType = GetType(); ruleList.Add(ruleType); Candidate = candidate; bool satisfied = Evaluate(candidate); if (!satisfied || (SoftCheck \u0026amp;\u0026amp; !string.IsNullOrEmpty(result.Message))) { result = new SpecificationResult { Satisfied = SoftCheck, Message = string.Format(MessageFormat(), candidate, Target) }; } return satisfied; } public AbstractSpecification\u0026lt;T\u0026gt; SuccessOrRhs(ISpecification\u0026lt;T\u0026gt; specification) { return new SuccessOrRhsSpecification\u0026lt;T\u0026gt;(specification); } } } ","permalink":"https://blog.mckelt.com/articles/posts/ispecification/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epublic interface ISpecification\u0026lt;T\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  bool IsSatisfiedBy(T candidate);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ISpecification\u0026lt;T\u0026gt; And(ISpecification\u0026lt;T\u0026gt; other);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ISpecification\u0026lt;T\u0026gt; Or(ISpecification\u0026lt;T\u0026gt; other);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ISpecification\u0026lt;T\u0026gt; XOr(ISpecification\u0026lt;T\u0026gt; other);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ISpecification\u0026lt;T\u0026gt; AndAllOf(IEnumerable\u0026lt;ISpecification\u0026lt;T\u0026gt;\u0026gt; specifications);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  T Target { get; set; }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  void GetResults(ResultsVisitor visitor);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  IEnumerable\u0026lt;Type\u0026gt; WhatWasAssessed();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Risks.IDemoCommand GetCommand();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e using System;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing System.Collections.Generic;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing Demo.Core.Commands;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing Demo.Core.Risks;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing Demo.Core.Specification.Common;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enamespace Demo.Core.Specification\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    public abstract class AbstractSpecification\u0026lt;T\u0026gt; : ISpecification\u0026lt;T\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        protected SpecificationResult result;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        protected IList\u0026lt;Type\u0026gt; ruleList = new List\u0026lt;Type\u0026gt;();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        protected bool SoftCheck { get; set; }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public T Candidate { get; set; }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public T Target { get; set; }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public bool IsReplay {protected get; set;}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public ISpecification\u0026lt;T\u0026gt; And(ISpecification\u0026lt;T\u0026gt; other)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return new AndSpecification\u0026lt;T\u0026gt;(this, other);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public ISpecification\u0026lt;T\u0026gt; Or(ISpecification\u0026lt;T\u0026gt; other)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return new OrSpecification\u0026lt;T\u0026gt;(this, other);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public ISpecification\u0026lt;T\u0026gt; XOr(ISpecification\u0026lt;T\u0026gt; other)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return new XORSpecification\u0026lt;T\u0026gt;(this, other);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public ISpecification\u0026lt;T\u0026gt; AndAllOf(IEnumerable\u0026lt;ISpecification\u0026lt;T\u0026gt;\u0026gt; specifications)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return new AndAllOfSpecification\u0026lt;T\u0026gt;(this, specifications);    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public virtual bool Evaluate(T candidate)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            throw new NotImplementedException(\u0026#34;You need to provide a predicate or override IsSatisfiedBy\u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public virtual IDemoCommand GetCommand()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return new NoCommand();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public virtual void GetResults(ResultsVisitor visitor)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            if (result != null \u0026amp;\u0026amp; !string.IsNullOrEmpty(result.Message))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                visitor.Add(result);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public virtual IEnumerable\u0026lt;Type\u0026gt; WhatWasAssessed()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return ruleList;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public virtual string MessageFormat()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            throw new NotImplementedException(\u0026#34;You need to provide a result a message or override IsSatisfiedBy\u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public virtual bool IsSatisfiedBy(T candidate)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            if (IsReplay)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                return true;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Type ruleType = GetType(); \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ruleList.Add(ruleType);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Candidate = candidate;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            bool satisfied = Evaluate(candidate);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            if (!satisfied || (SoftCheck \u0026amp;\u0026amp; !string.IsNullOrEmpty(result.Message)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                result = new SpecificationResult\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                Satisfied = SoftCheck, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                Message = string.Format(MessageFormat(), candidate, Target)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return satisfied;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public AbstractSpecification\u0026lt;T\u0026gt; SuccessOrRhs(ISpecification\u0026lt;T\u0026gt; specification)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return new SuccessOrRhsSpecification\u0026lt;T\u0026gt;(specification);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"ISpecification"},{"content":" const int maxSize = 52428800; var binding = new BasicHttpBinding(); binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None; binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName; binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default; binding.MaxReceivedMessageSize = 1000000; binding.CloseTimeout = new TimeSpan(0, 1, 0); binding.OpenTimeout = new TimeSpan(0,1,0); binding.ReceiveTimeout = new TimeSpan(0,10,0); binding.SendTimeout = new TimeSpan(0,1,0); binding.AllowCookies = false; binding.BypassProxyOnLocal = false; binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; binding.MaxBufferSize = maxSize; binding.MaxBufferPoolSize = maxSize; binding.MaxReceivedMessageSize = maxSize; binding.MessageEncoding = WSMessageEncoding.Mtom; binding.TextEncoding = Encoding.UTF8; binding.TransferMode = TransferMode.Buffered; binding.UseDefaultWebProxy = true; binding.ReaderQuotas.MaxDepth = 32; binding.ReaderQuotas.MaxStringContentLength = maxSize; binding.ReaderQuotas.MaxArrayLength = maxSize; binding.ReaderQuotas.MaxBytesPerRead = maxSize; binding.ReaderQuotas.MaxNameTableCharCount = maxSize; container = new IocContainer(LifestyleType.Transient); container.AddFacility\u0026lt;WcfFacility\u0026gt;().Register( Component .For\u0026lt;ISharePointFacadeService\u0026gt;() .Named(\u0026quot;DmsGateway\u0026quot;) .ActAs( new DefaultClientModel() { Endpoint = WcfEndpoint .BoundTo(binding) .At(\u0026quot;http://localhost/SharepointFacade/DMSService.svc/mex\u0026quot;) })); ","permalink":"https://blog.mckelt.com/articles/posts/castle-windsor-wcf-endpoint-configuration/","summary":"\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003e      const int maxSize = 52428800;\n\n        var binding = new BasicHttpBinding();\n        binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;\n        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;\n        binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;\n        binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;\n        binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;\n        binding.MaxReceivedMessageSize = 1000000;\n        binding.CloseTimeout = new TimeSpan(0, 1, 0);\n        binding.OpenTimeout = new TimeSpan(0,1,0);\n        binding.ReceiveTimeout = new TimeSpan(0,10,0);\n        binding.SendTimeout = new TimeSpan(0,1,0);\n        binding.AllowCookies = false;\n        binding.BypassProxyOnLocal = false;\n        binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;\n        binding.MaxBufferSize = maxSize;\n        binding.MaxBufferPoolSize = maxSize;\n        binding.MaxReceivedMessageSize = maxSize;\n        binding.MessageEncoding = WSMessageEncoding.Mtom;\n        binding.TextEncoding = Encoding.UTF8;\n        binding.TransferMode = TransferMode.Buffered;\n        binding.UseDefaultWebProxy = true;\n\n        binding.ReaderQuotas.MaxDepth = 32;\n        binding.ReaderQuotas.MaxStringContentLength = maxSize;\n        binding.ReaderQuotas.MaxArrayLength = maxSize;\n        binding.ReaderQuotas.MaxBytesPerRead = maxSize;\n        binding.ReaderQuotas.MaxNameTableCharCount = maxSize;\n\n        container = new IocContainer(LifestyleType.Transient);\n        container.AddFacility\u0026lt;WcfFacility\u0026gt;().Register(\n            Component\n                .For\u0026lt;ISharePointFacadeService\u0026gt;()\n                .Named(\u0026quot;DmsGateway\u0026quot;)\n                .ActAs(\n                    new DefaultClientModel()\n                    {\n                        Endpoint = WcfEndpoint\n                                    .BoundTo(binding)\n                                    .At(\u0026quot;http://localhost/SharepointFacade/DMSService.svc/mex\u0026quot;)\n                    }));\n\u003c/code\u003e\u003c/pre\u003e\u003c/blockquote\u003e","title":"Castle Windsor – WCF Endpoint Configuration"},{"content":" public static class Extensions { public static Hashtable ConvertPropertiesAndValuesToHashtable(this object obj) { var ht = new Hashtable();\n// get all public static properties of obj type var propertyInfos = obj.GetType().GetProperties().Where(a=\u0026gt;a.MemberType.Equals(MemberTypes.Property)).ToArray(); // sort properties by name Array.Sort(propertyInfos, (propertyInfo1, propertyInfo2) =\u0026gt; propertyInfo1.Name.CompareTo(propertyInfo2.Name)); // write property names foreach (PropertyInfo propertyInfo in propertyInfos) { ht.Add(propertyInfo.Name, propertyInfo.GetValue(obj, BindingFlags.Public, null, null, CultureInfo.CurrentCulture)); } return ht; } } Tests\nusing System; using System.Collections; using System.Globalization; using System.Linq; using System.Reflection;\nusing Microsoft.VisualStudio.TestTools.UnitTesting; using Presentation; using Presentation.Mappers; using Presentation.Model; using SoftwareApproach.TestingExtensions; using TestHelpers; \\[Concern(typeof(DocumentMetaDataToDmsDocumentMetaDataMapper))\\] \\[TestClass\\] public class WhenUsingExtensions : ContextSpecification\u0026lt;DocumentMetaDataToDmsDocumentMetaDataMapper\u0026gt; { private DocumentMetadata metadata; private Hashtable ht; protected override void Context() { metadata = RandomHelper.FillPropertiesWithRandomValues\u0026lt;DocumentMetadata\u0026gt;(new DocumentMetadata()); metadata.RiskId = 12; } protected override void Because() { ht = metadata.ConvertPropertiesAndValuesToHashtable(); } \\[TestMethod\\] public void ShouldContainCorrectCountForNumberOfMembers() { ht.Count.ShouldEqual(metadata.GetType().GetProperties().Where(a=\u0026gt;a.MemberType.Equals(MemberTypes.Property)).Count()); } \\[TestMethod\\] public void ShouldMapAllPropertiesToHashtableCorrectly() { metadata.Account.ShouldEqual(ht\\[\u0026quot;Account\u0026quot;\\].ToString()); metadata.AssociatedNames.ShouldEqual(ht\\[\u0026quot;AssociatedNames\u0026quot;\\].ToString()); metadata.Broker.ShouldEqual(ht\\[\u0026quot;Broker\u0026quot;\\].ToString()); metadata.BrokerContact.ShouldEqual(ht\\[\u0026quot;BrokerContact\u0026quot;\\].ToString()); metadata.CreatedDate.ShouldEqual(Convert.ToDateTime(ht\\[\u0026quot;CreatedDate\u0026quot;\\], CultureInfo.CurrentCulture)); metadata.ExpiryDate.ShouldEqual(Convert.ToDateTime(ht\\[\u0026quot;ExpiryDate\u0026quot;\\], CultureInfo.CurrentCulture)); metadata.InceptionDate.ShouldEqual(Convert.ToDateTime(ht\\[\u0026quot;InceptionDate\u0026quot;\\], CultureInfo.CurrentCulture)); metadata.PolicyReference.ShouldEqual(ht\\[\u0026quot;PolicyReference\u0026quot;\\].ToString()); metadata.QuoteReference.ShouldEqual(ht\\[\u0026quot;QuoteReference\u0026quot;\\].ToString()); metadata.RiskId.ShouldEqual(Convert.ToInt32(ht\\[\u0026quot;RiskId\u0026quot;\\])); metadata.Status.ShouldEqual(ht\\[\u0026quot;Status\u0026quot;\\].ToString()); metadata.Underwriter.ShouldEqual(ht\\[\u0026quot;Underwriter\u0026quot;\\].ToString()); metadata.UniqueMarketReference.ShouldEqual(ht\\[\u0026quot;UniqueMarketReference\u0026quot;\\].ToString()); metadata.YearOfAccount.ShouldEqual(Convert.ToInt32(ht\\[\u0026quot;YearOfAccount\u0026quot;\\])); } } ","permalink":"https://blog.mckelt.com/articles/posts/convertpropertiesandvaluestohashtable-extension-method/","summary":"\u003cblockquote\u003e\n\u003cp\u003epublic static class Extensions\n{\npublic static Hashtable ConvertPropertiesAndValuesToHashtable(this object obj)\n{\nvar ht = new Hashtable();\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e        // get all public static properties of obj type\n        var propertyInfos = obj.GetType().GetProperties().Where(a=\u0026gt;a.MemberType.Equals(MemberTypes.Property)).ToArray();\n        // sort properties by name\n        Array.Sort(propertyInfos, (propertyInfo1, propertyInfo2) =\u0026gt; propertyInfo1.Name.CompareTo(propertyInfo2.Name));\n\n        // write property names\n        foreach (PropertyInfo propertyInfo in propertyInfos)\n        {\n            ht.Add(propertyInfo.Name, propertyInfo.GetValue(obj, BindingFlags.Public, null, null, CultureInfo.CurrentCulture));\n        }\n\n        return ht;\n    }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTests\u003c/p\u003e\n\u003cp\u003eusing System;\nusing System.Collections;\nusing System.Globalization;\nusing System.Linq;\nusing System.Reflection;\u003c/p\u003e","title":"ConvertPropertiesAndValuesToHashtable Extension method"},{"content":"declare @vcFK varchar(250), @vcTable varchar(250), @vcSP varchar(250), @vcView varchar(250), @vcFn varchar(250) -- ...drop all foreign key constraints select @vcFK = min(name) from sysobjects where type=\u0026#39;F\u0026#39; while @vcFK is not null begin print \u0026#39;Dropping FK constraint \u0026#39; + @vcFK -- ...get name of table corresponding to the foreign key select @vcTable = S2.name from sysobjects S1 inner join sysconstraints C on S1.id = C.constid inner join sysobjects S2 on C.id = S2.id where S1.name = @vcFK and S1.type=\u0026#39;F\u0026#39; exec (\u0026#39;alter table \u0026#39; + @vcTable + \u0026#39; drop constraint \u0026#39; + @vcFK) select @vcFK = min(name) from sysobjects where type=\u0026#39;F\u0026#39; and name \u0026gt; @vcFK end -- ...drop all tables select @vcTable = min(name) from sysobjects where type=\u0026#39;U\u0026#39; and name not like \u0026#39;dt%\u0026#39; while @vcTable is not null begin print \u0026#39;Dropping table \u0026#39; + @vcTable exec (\u0026#39;drop table \u0026#39; + @vcTable) select @vcTable = min(name) from sysobjects where type=\u0026#39;U\u0026#39; and name not like \u0026#39;dt%\u0026#39; and name \u0026gt; @vcTable end -- ...drop all our stored procedures select @vcSP = min(name) from sysobjects where type=\u0026#39;P\u0026#39; and (name like \u0026#39;usp%\u0026#39;) while @vcSP is not null begin print \u0026#39;Dropping procedure \u0026#39; + @vcSP exec (\u0026#39;drop procedure \u0026#39; + @vcSP) select @vcSP = min(name) from sysobjects where type=\u0026#39;P\u0026#39; and (name like \u0026#39;usp%\u0026#39;) and name \u0026gt; @vcSP end -- ...drop all views select @vcView = min(name) from sysobjects where type=\u0026#39;V\u0026#39; and name like \u0026#39;v%\u0026#39; while @vcView is not null begin print \u0026#39;Dropping view \u0026#39; + @vcView exec (\u0026#39;drop view \u0026#39; + @vcView) select @vcView = min(name) from sysobjects where type=\u0026#39;V\u0026#39; and name like \u0026#39;v%\u0026#39; and name \u0026gt; @vcView end -- ...drop all functions select @vcFn = min(name) from sysobjects where type=\u0026#39;FN\u0026#39; and name like \u0026#39;udf%\u0026#39; while @vcFn is not null begin print \u0026#39;Dropping function \u0026#39; + @vcFn exec (\u0026#39;drop function \u0026#39; + @vcFn) select @vcFn = min(name) from sysobjects where type=\u0026#39;FN\u0026#39; and name like \u0026#39;udf%\u0026#39; and name \u0026gt; @vcFn end ","permalink":"https://blog.mckelt.com/articles/posts/obliterate-database/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edeclare\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK varchar(\u003cspan style=\"color:#099\"\u003e250\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable varchar(\u003cspan style=\"color:#099\"\u003e250\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcSP varchar(\u003cspan style=\"color:#099\"\u003e250\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcView varchar(\u003cspan style=\"color:#099\"\u003e250\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFn varchar(\u003cspan style=\"color:#099\"\u003e250\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- ...drop all foreign key constraints      \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eselect \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;F\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#00a\"\u003ewhile\u003c/span\u003e \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK is \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e null\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebegin\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#0aa\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#39;Dropping FK constraint \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   -- ...get name of table corresponding to the foreign key\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   select\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable = S2.name\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   from\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      sysobjects S1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      inner join sysconstraints C on S1.id = C.constid\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      inner join sysobjects S2 on C.id = S2.id\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   where\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      S1.name = \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e S1.type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;F\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   exec (\u003cspan style=\"color:#a50\"\u003e\u0026#39;alter table \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable + \u003cspan style=\"color:#a50\"\u003e\u0026#39; drop constraint \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   select \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;F\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name \u0026gt; \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFK\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eend\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- ...drop all tables\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eselect \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;U\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e like \u003cspan style=\"color:#a50\"\u003e\u0026#39;dt%\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#00a\"\u003ewhile\u003c/span\u003e \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable is \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e null\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebegin\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#0aa\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#39;Dropping table \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   exec (\u003cspan style=\"color:#a50\"\u003e\u0026#39;drop table \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   select \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;U\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e like \u003cspan style=\"color:#a50\"\u003e\u0026#39;dt%\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name \u0026gt; \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcTable\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eend\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- ...drop all our stored procedures\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eselect \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcSP = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e (name like \u003cspan style=\"color:#a50\"\u003e\u0026#39;usp%\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#00a\"\u003ewhile\u003c/span\u003e \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcSP is \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e null\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebegin\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#0aa\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#39;Dropping procedure \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcSP\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   exec (\u003cspan style=\"color:#a50\"\u003e\u0026#39;drop procedure \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcSP)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   select \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcSP = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e (name like \u003cspan style=\"color:#a50\"\u003e\u0026#39;usp%\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name \u0026gt; \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcSP\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eend\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- ...drop all views\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eselect \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcView = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;V\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name like \u003cspan style=\"color:#a50\"\u003e\u0026#39;v%\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#00a\"\u003ewhile\u003c/span\u003e \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcView is \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e null\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebegin\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#0aa\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#39;Dropping view \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcView\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   exec (\u003cspan style=\"color:#a50\"\u003e\u0026#39;drop view \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcView)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   select \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcView = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;V\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name like \u003cspan style=\"color:#a50\"\u003e\u0026#39;v%\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name \u0026gt; \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcView\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eend\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-- ...drop all functions\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eselect \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFn = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;FN\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name like \u003cspan style=\"color:#a50\"\u003e\u0026#39;udf%\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#00a\"\u003ewhile\u003c/span\u003e \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFn is \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e null\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebegin\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#0aa\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#a50\"\u003e\u0026#39;Dropping function \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   exec (\u003cspan style=\"color:#a50\"\u003e\u0026#39;drop function \u0026#39;\u003c/span\u003e + \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFn)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   select \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFn = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e(name) from sysobjects where type=\u003cspan style=\"color:#a50\"\u003e\u0026#39;FN\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name like \u003cspan style=\"color:#a50\"\u003e\u0026#39;udf%\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e name \u0026gt; \u003cspan style=\"color:#f00;background-color:#faa\"\u003e@\u003c/span\u003evcFn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eend\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Obliterate Database"},{"content":"In the web.config in between the tags\n\u0026lt;system.diagnostics\u0026gt;\n\u0026lt;sources\u0026gt;\n\u0026lt;source name=\u0026ldquo;System.ServiceModel\u0026rdquo; switchValue=\u0026ldquo;Information, ActivityTracing\u0026rdquo; propagateActivity=\u0026ldquo;true\u0026rdquo;\u0026gt;\n\u0026lt;listeners\u0026gt;\n\u0026lt;add name=\u0026ldquo;traceListener\u0026rdquo; type=\u0026ldquo;System.Diagnostics.XmlWriterTraceListener\u0026rdquo; initializeData= \u0026ldquo;WCFTrace.svclog\u0026rdquo; /\u0026gt;\n\u0026lt;/listeners\u0026gt;\n\u0026lt;/source\u0026gt;\n\u0026lt;/sources\u0026gt;\n\u0026lt;trace autoflush=\u0026ldquo;true\u0026rdquo; /\u0026gt;\n\u0026lt;/system.diagnostics\u0026gt;\n","permalink":"https://blog.mckelt.com/articles/posts/wcf-tracing/","summary":"\u003cp\u003eIn the web.config in between the \u003cconfiguration\u003e\u003c/configuration\u003e tags\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e \u0026lt;system.diagnostics\u0026gt;\u003cbr\u003e\n\u0026lt;sources\u0026gt;\u003cbr\u003e\n\u0026lt;source name=\u0026ldquo;System.ServiceModel\u0026rdquo;\nswitchValue=\u0026ldquo;Information, ActivityTracing\u0026rdquo;\npropagateActivity=\u0026ldquo;true\u0026rdquo;\u0026gt;\u003cbr\u003e\n\u0026lt;listeners\u0026gt;\u003cbr\u003e\n\u0026lt;add name=\u0026ldquo;traceListener\u0026rdquo;\ntype=\u0026ldquo;System.Diagnostics.XmlWriterTraceListener\u0026rdquo;\ninitializeData= \u0026ldquo;WCFTrace.svclog\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;/listeners\u0026gt;\u003cbr\u003e\n\u0026lt;/source\u0026gt;\u003cbr\u003e\n\u0026lt;/sources\u0026gt;\u003cbr\u003e\n\u0026lt;trace autoflush=\u0026ldquo;true\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;/system.diagnostics\u0026gt;\u003c/p\u003e\u003c/blockquote\u003e","title":"WCF Tracing"},{"content":"Log4Net config \u0026lt;? xml version\\=\u0026quot;1.0\u0026quot; encoding\\=\u0026quot;utf-8\u0026quot; ?\\\u0026gt; \u0026lt;configuration\u0026gt;\n\u0026lt;log4net\u0026gt;\n\u0026lt;appender name=\u0026ldquo;WindowsEventAppender\u0026rdquo; type=\u0026ldquo;log4net.Appender.EventLogAppender\u0026rdquo;\u0026gt;\n\u0026lt;param name=\u0026ldquo;LogName\u0026rdquo; value=\u0026ldquo;Application\u0026rdquo; /\u0026gt;\n\u0026lt;applicationName value=\u0026ldquo;Phoenix\u0026rdquo; /\u0026gt;\n\u0026lt;layout type=\u0026ldquo;log4net.Layout.PatternLayout\u0026rdquo;\u0026gt;\n\u0026lt;conversionPattern value=\u0026quot;%date [%thread] %-5level %logger%newline =\u0026gt; %message%newline\u0026quot; /\u0026gt;\n\u0026lt;/layout\u0026gt;\n\u0026lt;filter type=\u0026ldquo;log4net.Filter.LevelRangeFilter\u0026rdquo;\u0026gt;\n\u0026lt;param name=\u0026ldquo;LevelMin\u0026rdquo; value=\u0026ldquo;DEBUG\u0026rdquo; /\u0026gt;\n\u0026lt;/filter\u0026gt;\n\u0026lt;/appender\u0026gt;\n\u0026lt;appender name=\u0026ldquo;RollingFile\u0026rdquo; type=\u0026ldquo;log4net.Appender.RollingFileAppender\u0026rdquo;\u0026gt;\n\u0026lt;file type=\u0026ldquo;log4net.Util.PatternString\u0026rdquo; value=\u0026ldquo;logs\\\\phoenix.log\u0026rdquo; /\u0026gt;\n\u0026lt;appendToFile value=\u0026ldquo;true\u0026rdquo; /\u0026gt;\n\u0026lt;maximumFileSize value=\u0026ldquo;500KB\u0026rdquo; /\u0026gt;\n\u0026lt;maxSizeRollBackups value=\u0026ldquo;2\u0026rdquo; /\u0026gt;\n\u0026lt;layout type=\u0026ldquo;log4net.Layout.PatternLayout\u0026rdquo;\u0026gt;\n\u0026lt;conversionPattern value=\u0026quot;%date [%thread] %-5level %logger%newline =\u0026gt; %message%newline\u0026quot; /\u0026gt;\n\u0026lt;/layout\u0026gt;\n\u0026lt;/appender\u0026gt; \u0026lt;root\u0026gt;\n\u0026lt;level value=\u0026ldquo;DEBUG\u0026rdquo; /\u0026gt; \u0026lt;appender-ref ref=\u0026ldquo;WindowsEventAppender\u0026rdquo; /\u0026gt;\n\u0026lt;appender-ref ref=\u0026ldquo;RollingFile\u0026rdquo; /\u0026gt;\n\u0026lt;/root\u0026gt;\n\u0026lt;/log4net\u0026gt;\n\u0026lt;/configuration\u0026gt;\n","permalink":"https://blog.mckelt.com/articles/posts/log4net-config/","summary":"\u003ch2 id=\"log4net-config\"\u003eLog4Net config\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026lt;?  xml version\\=\u0026quot;1.0\u0026quot; encoding\\=\u0026quot;utf-8\u0026quot; ?\\\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u0026lt;configuration\u0026gt;\u003cbr\u003e\n\u0026lt;log4net\u0026gt;\u003cbr\u003e\n\u0026lt;appender name=\u0026ldquo;WindowsEventAppender\u0026rdquo; type=\u0026ldquo;log4net.Appender.EventLogAppender\u0026rdquo;\u0026gt;\u003cbr\u003e\n\u0026lt;param name=\u0026ldquo;LogName\u0026rdquo; value=\u0026ldquo;Application\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;applicationName value=\u0026ldquo;Phoenix\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;layout type=\u0026ldquo;log4net.Layout.PatternLayout\u0026rdquo;\u0026gt;\u003cbr\u003e\n\u0026lt;conversionPattern value=\u0026quot;%date [%thread] %-5level %logger%newline =\u0026gt; %message%newline\u0026quot; /\u0026gt;\u003cbr\u003e\n\u0026lt;/layout\u0026gt;\u003cbr\u003e\n\u0026lt;filter type=\u0026ldquo;log4net.Filter.LevelRangeFilter\u0026rdquo;\u0026gt;\u003cbr\u003e\n\u0026lt;param name=\u0026ldquo;LevelMin\u0026rdquo; value=\u0026ldquo;DEBUG\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;/filter\u0026gt;\u003cbr\u003e\n\u0026lt;/appender\u0026gt;\u003cbr\u003e\n\u0026lt;appender name=\u0026ldquo;RollingFile\u0026rdquo; type=\u0026ldquo;log4net.Appender.RollingFileAppender\u0026rdquo;\u0026gt;\u003cbr\u003e\n\u0026lt;file type=\u0026ldquo;log4net.Util.PatternString\u0026rdquo;   value=\u0026ldquo;logs\\\\phoenix.log\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;appendToFile value=\u0026ldquo;true\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;maximumFileSize value=\u0026ldquo;500KB\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;maxSizeRollBackups value=\u0026ldquo;2\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;layout type=\u0026ldquo;log4net.Layout.PatternLayout\u0026rdquo;\u0026gt;\u003cbr\u003e\n\u0026lt;conversionPattern value=\u0026quot;%date [%thread] %-5level %logger%newline =\u0026gt; %message%newline\u0026quot; /\u0026gt;\u003cbr\u003e\n\u0026lt;/layout\u0026gt;\u003cbr\u003e\n\u0026lt;/appender\u0026gt; \u003cbr\u003e\n\u0026lt;root\u0026gt;\u003cbr\u003e\n\u0026lt;level value=\u0026ldquo;DEBUG\u0026rdquo; /\u0026gt; \u003cbr\u003e\n\u0026lt;appender-ref ref=\u0026ldquo;WindowsEventAppender\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;appender-ref ref=\u0026ldquo;RollingFile\u0026rdquo; /\u0026gt;\u003cbr\u003e\n\u0026lt;/root\u0026gt;\u003cbr\u003e\n\u0026lt;/log4net\u0026gt;\u003cbr\u003e\n\u0026lt;/configuration\u0026gt;\u003c/p\u003e","title":"Log4Net config"},{"content":"Context Specification Base Class namespace Example { using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Rhino.Mocks;\npublic abstract class ContextSpecification\u0026lt;T\u0026gt; { protected Exception executionException; protected T sut { get; set; } [TestInitialize\\] public void Start() { this.Context(); this.SetupMockResults(); this.Because(); } [TestCleanup\\] public void CleanUp() { this.Clean(); } protected virtual void Context() { } protected virtual void SetupMockResults() { } protected virtual void Because() { } protected virtual void Clean() { } protected TInterface GetDependency\u0026lt;TInterface\u0026gt;() where TInterface : class { return MockRepository.GenerateMock\u0026lt;TInterface\u0026gt;(); } public void Execute(Action action) { try { action(); } catch (Exception ex) { executionException = ex; } } } }\n","permalink":"https://blog.mckelt.com/articles/posts/context-specification/","summary":"\u003ch1 id=\"context-specification-base-class\"\u003eContext Specification Base Class\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003enamespace Example\n{\nusing System;\nusing Microsoft.VisualStudio.TestTools.UnitTesting;\nusing Rhino.Mocks;\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003epublic abstract class ContextSpecification\u0026lt;T\u0026gt;\n{\n    protected Exception executionException;\n\n    protected T sut { get; set; }\n\n    [TestInitialize\\]\n    public void Start()\n    {\n        this.Context();\n        this.SetupMockResults();\n        this.Because();\n    }\n\n    [TestCleanup\\]\n    public void CleanUp()\n    {\n        this.Clean();\n    }\n\n    protected virtual void Context()\n    {\n    }\n\n    protected virtual void SetupMockResults()\n    {\n    }\n\n    protected virtual void Because()\n    {\n    }\n\n    protected virtual void Clean()\n    {\n    }\n\n    protected TInterface GetDependency\u0026lt;TInterface\u0026gt;() where TInterface : class\n    {\n        return MockRepository.GenerateMock\u0026lt;TInterface\u0026gt;();\n    }\n\n    public void Execute(Action action)\n    {\n        try\n        {\n            action();\n        }\n        catch (Exception ex)\n        {\n            executionException = ex;\n        }\n    }\n\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e}\u003c/p\u003e","title":"Context Specification"},{"content":" CREATE PROCEDURE AS BEGIN SET NOCOUNT ON BEGIN TRY\n--Do work END TRY\nBEGIN CATCH /* Note that catching and rethrowing an exception is a lossy operation. ERROR_PROCEDURE() etc will be reset. */ DECLARE @errorMessage NVARCHAR(4000); DECLARE @errorSeverity INT; DECLARE @errorState INT;\nSELECT @errorMessage = ERROR\\_MESSAGE(), @errorSeverity = ERROR\\_SEVERITY() , @errorState = ERROR\\_STATE(); --Perform required recovery actions. RAISERROR ( @errorMessage, @errorSeverity, @errorState ); RETURN 1; END CATCH\nRETURN 0; END\n","permalink":"https://blog.mckelt.com/articles/posts/sql-server-error-handling/","summary":"\u003cblockquote\u003e\n\u003cp\u003eCREATE PROCEDURE \u003cprocName\u003e\nAS\nBEGIN\nSET NOCOUNT ON\nBEGIN TRY\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e  --Do work\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eEND TRY\u003c/p\u003e\n\u003cp\u003eBEGIN CATCH\n/* Note that catching and rethrowing an exception is a lossy operation. ERROR_PROCEDURE() etc will be reset. */\nDECLARE @errorMessage   NVARCHAR(4000);\nDECLARE @errorSeverity  INT;\nDECLARE @errorState     INT;\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e  SELECT  @errorMessage   = ERROR\\_MESSAGE(),\n          @errorSeverity  = ERROR\\_SEVERITY() ,\n          @errorState     = ERROR\\_STATE();\n\n  --Perform required recovery actions.\n\n  RAISERROR ( @errorMessage, @errorSeverity, @errorState );\n  \n  RETURN 1;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eEND CATCH\u003c/p\u003e","title":"SQL Server error handling"},{"content":"\n","permalink":"https://blog.mckelt.com/articles/posts/resharper-live-templates/","summary":"\u003cp\u003e\u003cimg alt=\"image\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120915872-c416db80-c6d8-11eb-8019-37548db1e340.png\"\u003e\u003c/p\u003e","title":"Resharper Live Templates"},{"content":"All these extension methods are now contained here\nhttps://github.com/chrismckelt/ExtensionMinder\nand available on nuget at\nhttps://www.nuget.org/packages/ExtensionMinder/\n","permalink":"https://blog.mckelt.com/articles/posts/extensions-methods/","summary":"\u003cp\u003eAll these extension methods are now contained here\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/chrismckelt/ExtensionMinder\" target=\"_blank\"\u003ehttps://github.com/chrismckelt/ExtensionMinder\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eand available on nuget at\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.nuget.org/packages/ExtensionMinder/\" target=\"_blank\"\u003ehttps://www.nuget.org/packages/ExtensionMinder/\u003c/a\u003e\u003c/p\u003e","title":"Extensions Methods"},{"content":" using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace TestHelpers { public static class RandomHelper { /* This method can be used to fill all public properties of an object with random values depending on their type. CAUTION: it does not fill attributes that end with \u0026#39;ID\u0026#39; or attributes which are called \u0026#39;pk\u0026#39;. They have to be filled manually.*/ private static readonly Random randomSeed = new Random(); /* Generates a random string with the given length*/ public static T FillPropertiesWithRandomValues\u0026lt;T\u0026gt;(bool fillBaseObjects) { return CreateItem\u0026lt;T\u0026gt;(true); } public static T FillPropertiesWithRandomValues\u0026lt;T\u0026gt;() { return CreateItem\u0026lt;T\u0026gt;(false); } private static T CreateItem\u0026lt;T\u0026gt;(bool fillBaseObjects) { Type type = typeof (T); var item = (T) Activator.CreateInstance(typeof (T)); while (type != null) { PropertyInfo[] infos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (infos.Length == 0) { if (item.GetType().BaseType != null) { infos = item.GetType().BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); } } foreach (PropertyInfo info in infos) { Type infoType = info.PropertyType; Type nullableType = null; if (infoType.IsGenericType \u0026amp;\u0026amp; infoType.GetGenericTypeDefinition().Equals(typeof (Nullable\u0026lt;\u0026gt;))) { nullableType = ExtractTypeFromNullable(infoType); } if (!info.CanWrite) continue; if (infoType.Equals(typeof (DateTime)) || infoType.Equals(typeof (DateTime?))) { info.SetValue(item, RandomDateTime(DateTime.Now, new DateTime(3000, 01, 01)), null); } else if (infoType.Equals(typeof (string))) { info.SetValue(item, info.Name + \u0026#34;_\u0026#34; + RandomString(20, false), null); } else if ((infoType.Equals(typeof (long)) || infoType.Equals(typeof (double)) || infoType.Equals(typeof (int)) || infoType.Equals(typeof (long)) || infoType.Equals(typeof (int))) \u0026amp;\u0026amp; !info.Name.ToLower().EndsWith(\u0026#34;id\u0026#34;) \u0026amp;\u0026amp; !info.Name.ToLower().Equals(\u0026#34;pk\u0026#34;)) { info.SetValue(item, RandomNumber(0, 999999), null); } else if ((infoType.Equals(typeof (long?)) || infoType.Equals(typeof (double?)) || infoType.Equals(typeof (int?)) || infoType.Equals(typeof (long?)) || infoType.Equals(typeof (int?))) \u0026amp;\u0026amp; !info.Name.ToLower().EndsWith(\u0026#34;id\u0026#34;) \u0026amp;\u0026amp; !info.Name.ToLower().Equals(\u0026#34;pk\u0026#34;)) { Type genericType = info.PropertyType.GetGenericArguments()[0]; info.SetValue(item, Convert.ChangeType(RandomNumber(0, 999999), genericType), null); } else if (infoType.Equals(typeof (decimal))) { info.SetValue(item, 1m, null); } else if (infoType.Equals(typeof (bool))) { info.SetValue(item, true, null); } else if (infoType.Equals(typeof (Guid))) { info.SetValue(item, Guid.NewGuid(), null); } else if (infoType.Equals(typeof (Enum))) { Array values = Enum.GetValues(infoType); List\u0026lt;object\u0026gt; list = values.Cast\u0026lt;object\u0026gt;().ToList(); object val = list[new Random().Next(0, list.Count)]; info.SetValue(item, val, null); } else if (((infoType.BaseType != null) \u0026amp;\u0026amp; (infoType.BaseType.Equals(typeof (Enum))))) { Array values = Enum.GetValues(infoType); List\u0026lt;object\u0026gt; list = values.Cast\u0026lt;object\u0026gt;().ToList(); object val = list[new Random().Next(0, list.Count)]; info.SetValue(item, val, null); } else if (nullableType != null) { if (nullableType.BaseType.Equals(typeof (Enum))) { Array values = Enum.GetValues(nullableType); List\u0026lt;object\u0026gt; list = values.Cast\u0026lt;object\u0026gt;().ToList(); object val = list[new Random().Next(0, list.Count)]; info.SetValue(item, val, null); } } else if (infoType.IsArray) { Console.WriteLine(\u0026#34;Object contains array of objects need to fill these\u0026#34;); MethodInfo sm = info.GetSetMethod(true); if (sm.ReturnType.IsArray) { object arrayObject = sm.Invoke(item, null); foreach (object element in (Array) arrayObject) { foreach (PropertyInfo arrayObjPinfo in element.GetType().GetProperties()) { Console.WriteLine(arrayObjPinfo.Name + \u0026#34;:\u0026#34; + arrayObjPinfo.GetGetMethod().Invoke(element, null)); } } } } } if (!fillBaseObjects) break; type = type.BaseType; } return item; } ///\u0026lt;summary\u0026gt;Indentify and extracting type from Nullable Type\u0026lt;/summary\u0026gt; public static Type ExtractTypeFromNullable(Type type) { if (type.IsGenericType \u0026amp;\u0026amp; type.GetGenericTypeDefinition() == typeof (Nullable\u0026lt;\u0026gt;)) { PropertyInfo valueProp = type.GetProperty(\u0026#34;Value\u0026#34;); return valueProp.PropertyType; } else { return null; } } public static string RandomString(int size, bool lowerCase) { var randomString = new StringBuilder(size); /* Ascii start position (65 = A / 97 = a)*/ int start = lowerCase ? 97 : 65; /* Add random chars*/ for (int i = 0; i \u0026lt; size; i++) { randomString.Append((char) ((26*randomSeed.NextDouble()) + start)); } return randomString.ToString(); } public static int RandomNumber(int minimal, int maximal) { return randomSeed.Next(minimal, maximal); } /* Returns a random boolean value*/ public static bool RandomBool() { return randomSeed.NextDouble() \u0026gt; 0.5; } /* Returns a random color*/ public static DateTime RandomDateTime(DateTime min, DateTime max) { if (max \u0026lt;= min) { const string message = \u0026#34;Max must be greater than min.\u0026#34;; throw new ArgumentException(message); } long minTicks = min.Ticks; long maxTicks = max.Ticks; double rn = ((Convert.ToDouble(maxTicks) - Convert.ToDouble(minTicks))*randomSeed.NextDouble()) + Convert.ToDouble(minTicks); return new DateTime(Convert.ToInt64(rn)); } } } ","permalink":"https://blog.mckelt.com/articles/posts/randomhelper/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing System;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing System.Collections.Generic;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing System.Linq;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing System.Reflection;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusing System.Text;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enamespace TestHelpers\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eclass\u003c/span\u003e RandomHelper\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        /* This method can be used to fill all public properties of an object with random values depending on their type.      CAUTION: it does \u003cspan style=\"color:#00a\"\u003enot\u003c/span\u003e fill attributes that end with \u003cspan style=\"color:#a50\"\u003e\u0026#39;ID\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eor\u003c/span\u003e attributes which are called \u003cspan style=\"color:#a50\"\u003e\u0026#39;pk\u0026#39;\u003c/span\u003e. They have to be filled manually.*/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        private \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e readonly Random randomSeed = new Random();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        /* Generates a random string with the given length*/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e T FillPropertiesWithRandomValues\u0026lt;T\u0026gt;(bool fillBaseObjects)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e CreateItem\u0026lt;T\u0026gt;(\u003cspan style=\"color:#0aa\"\u003etrue\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e T FillPropertiesWithRandomValues\u0026lt;T\u0026gt;()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e CreateItem\u0026lt;T\u0026gt;(\u003cspan style=\"color:#0aa\"\u003efalse\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        private \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e T CreateItem\u0026lt;T\u0026gt;(bool fillBaseObjects)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Type type = \u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (T);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e item = (T) Activator.CreateInstance(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (T));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ewhile\u003c/span\u003e (type != null)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                PropertyInfo[] infos =\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infos.Length == \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (item.GetType().BaseType != null)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        infos =\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            item.GetType().BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                                                  BindingFlags.DeclaredOnly);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                foreach (PropertyInfo info \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e infos)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    Type infoType = info.PropertyType;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    Type nullableType = null;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.IsGenericType \u0026amp;\u0026amp; infoType.GetGenericTypeDefinition().Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (Nullable\u0026lt;\u0026gt;)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        nullableType = ExtractTypeFromNullable(infoType);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (!info.CanWrite) \u003cspan style=\"color:#00a\"\u003econtinue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (DateTime)) || infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (DateTime\u003cspan style=\"color:#f00;background-color:#faa\"\u003e?\u003c/span\u003e)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, RandomDateTime(DateTime.Now, new DateTime(\u003cspan style=\"color:#099\"\u003e3000\u003c/span\u003e, \u003cspan style=\"color:#099\"\u003e01\u003c/span\u003e, \u003cspan style=\"color:#099\"\u003e01\u003c/span\u003e)), null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (string)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, info.Name + \u003cspan style=\"color:#a50\"\u003e\u0026#34;_\u0026#34;\u003c/span\u003e + RandomString(\u003cspan style=\"color:#099\"\u003e20\u003c/span\u003e, \u003cspan style=\"color:#0aa\"\u003efalse\u003c/span\u003e), null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e ((infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (long)) || infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (double)) ||\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                              infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (int)) || infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (long)) ||\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                              infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (int))) \u0026amp;\u0026amp; !info.Name.ToLower().EndsWith(\u003cspan style=\"color:#a50\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e) \u0026amp;\u0026amp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             !info.Name.ToLower().Equals(\u003cspan style=\"color:#a50\"\u003e\u0026#34;pk\u0026#34;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, RandomNumber(\u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#099\"\u003e999999\u003c/span\u003e), null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e ((infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (long\u003cspan style=\"color:#f00;background-color:#faa\"\u003e?\u003c/span\u003e)) || infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (double\u003cspan style=\"color:#f00;background-color:#faa\"\u003e?\u003c/span\u003e)) ||\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                              infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (int\u003cspan style=\"color:#f00;background-color:#faa\"\u003e?\u003c/span\u003e)) || infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (long\u003cspan style=\"color:#f00;background-color:#faa\"\u003e?\u003c/span\u003e)) ||\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                              infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (int\u003cspan style=\"color:#f00;background-color:#faa\"\u003e?\u003c/span\u003e))) \u0026amp;\u0026amp; !info.Name.ToLower().EndsWith(\u003cspan style=\"color:#a50\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e) \u0026amp;\u0026amp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             !info.Name.ToLower().Equals(\u003cspan style=\"color:#a50\"\u003e\u0026#34;pk\u0026#34;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        Type genericType = info.PropertyType.GetGenericArguments()[\u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, Convert.ChangeType(RandomNumber(\u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#099\"\u003e999999\u003c/span\u003e), genericType), null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (decimal)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, \u003cspan style=\"color:#099\"\u003e1\u003c/span\u003em, null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (bool)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, \u003cspan style=\"color:#0aa\"\u003etrue\u003c/span\u003e, null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (Guid)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, Guid.NewGuid(), null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (Enum)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        Array values = Enum.GetValues(infoType);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        List\u0026lt;object\u0026gt; list = values.Cast\u0026lt;object\u0026gt;().ToList();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        object val = list[new Random().Next(\u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, list.Count)];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, val, null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (((infoType.BaseType != null) \u0026amp;\u0026amp; (infoType.BaseType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (Enum)))))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        Array values = Enum.GetValues(infoType);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        List\u0026lt;object\u0026gt; list = values.Cast\u0026lt;object\u0026gt;().ToList();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        object val = list[new Random().Next(\u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, list.Count)];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        info.SetValue(item, val, null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (nullableType != null)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (nullableType.BaseType.Equals(\u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (Enum)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            Array values = Enum.GetValues(nullableType);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            List\u0026lt;object\u0026gt; list = values.Cast\u0026lt;object\u0026gt;().ToList();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            object val = list[new Random().Next(\u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e, list.Count)];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            info.SetValue(item, val, null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (infoType.IsArray)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        Console.WriteLine(\u003cspan style=\"color:#a50\"\u003e\u0026#34;Object contains array of objects need to fill these\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        MethodInfo sm = info.GetSetMethod(\u003cspan style=\"color:#0aa\"\u003etrue\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (sm.ReturnType.IsArray)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            object arrayObject = sm.Invoke(item, null);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            foreach (object element \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e (Array) arrayObject)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                foreach (PropertyInfo arrayObjPinfo \u003cspan style=\"color:#00a\"\u003ein\u003c/span\u003e element.GetType().GetProperties())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                    Console.WriteLine(arrayObjPinfo.Name + \u003cspan style=\"color:#a50\"\u003e\u0026#34;:\u0026#34;\u003c/span\u003e +\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                                      arrayObjPinfo.GetGetMethod().Invoke(element, null));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (!fillBaseObjects)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#00a\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                type = type.BaseType;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e item;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ///\u0026lt;summary\u0026gt;Indentify \u003cspan style=\"color:#00a\"\u003eand\u003c/span\u003e extracting type from Nullable Type\u0026lt;/summary\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e Type ExtractTypeFromNullable(Type type)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (type.IsGenericType \u0026amp;\u0026amp; type.GetGenericTypeDefinition() == \u003cspan style=\"color:#0aa\"\u003etypeof\u003c/span\u003e (Nullable\u0026lt;\u0026gt;))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                PropertyInfo valueProp = type.GetProperty(\u003cspan style=\"color:#a50\"\u003e\u0026#34;Value\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e valueProp.PropertyType;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e null;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e string RandomString(int size, bool lowerCase)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003evar\u003c/span\u003e randomString = new StringBuilder(size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            /* Ascii start position (\u003cspan style=\"color:#099\"\u003e65\u003c/span\u003e = A / \u003cspan style=\"color:#099\"\u003e97\u003c/span\u003e = a)*/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            int start = lowerCase \u003cspan style=\"color:#f00;background-color:#faa\"\u003e?\u003c/span\u003e \u003cspan style=\"color:#099\"\u003e97\u003c/span\u003e : \u003cspan style=\"color:#099\"\u003e65\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            /* Add random chars*/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003efor\u003c/span\u003e (int i = \u003cspan style=\"color:#099\"\u003e0\u003c/span\u003e; i \u0026lt; size; i++)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                randomString.Append((char) ((\u003cspan style=\"color:#099\"\u003e26\u003c/span\u003e*randomSeed.NextDouble()) + start));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e randomString.ToString();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e int RandomNumber(int minimal, int maximal)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e randomSeed.Next(minimal, maximal);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        /* Returns a random boolean value*/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e bool RandomBool()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e randomSeed.NextDouble() \u0026gt; \u003cspan style=\"color:#099\"\u003e0.5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        /* Returns a random color*/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public \u003cspan style=\"color:#00a\"\u003estatic\u003c/span\u003e DateTime RandomDateTime(DateTime \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e, DateTime \u003cspan style=\"color:#0aa\"\u003emax\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#0aa\"\u003emax\u003c/span\u003e \u0026lt;= \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#00a\"\u003econst\u003c/span\u003e string message = \u003cspan style=\"color:#a50\"\u003e\u0026#34;Max must be greater than min.\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                throw new ArgumentException(message);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            long minTicks = \u003cspan style=\"color:#0aa\"\u003emin\u003c/span\u003e.Ticks;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            long maxTicks = \u003cspan style=\"color:#0aa\"\u003emax\u003c/span\u003e.Ticks;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            double rn = ((Convert.ToDouble(maxTicks) - Convert.ToDouble(minTicks))*randomSeed.NextDouble()) +\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        Convert.ToDouble(minTicks);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#00a\"\u003ereturn\u003c/span\u003e new DateTime(Convert.ToInt64(rn));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"RandomHelper"},{"content":"The Open/Closed Principle Software entities (classes, modules, etc) should be open for extension, but closed for modification\nThe Liskov Substitution Principle Liskov\u0026rsquo;s notion of \u0026ldquo;subtype\u0026rdquo; is based on the notion of substitutability; that is, if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program (e.g., correctness). ie Derived classes must be usable through the base class interface without the need for the user to know the difference\nThe Dependency Inversion Principle High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.\nThe Interface Segregation Principle The dependency of one class to another one should depend on the smallest possible interface. Many client specific interfaces are better than one general purpose interface/\nThe Reuse/Release Equivalency Principle The unit of reuse is the unit of release. Effective reuse requires tracking of releases from a change control system. The package is the effective unit of reuse and release.\nThe Common Closure Principle Classes that change together, belong together.\nCommon Reuse Principle The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all\nThe Acyclic Dependencies Principle The dependency structure between packages must be a Directed Acyclic Graph (DAG).\nThe Stable Dependencies Principle Dependencies between released categories must run in the direction of stability. The dependee must be more stable than the depender.\nThe Stable Abstractions Principle The more stable a class category is, the more it must consist of abstract classes. A completely stable category should consist of nothing but abstract classes.\n","permalink":"https://blog.mckelt.com/articles/posts/design-principles/","summary":"\u003ch2 id=\"the-openclosed-principle\"\u003eThe Open/Closed Principle\u003c/h2\u003e\n\u003cp\u003eSoftware entities (classes, modules, etc) should be open for extension, but closed for modification\u003c/p\u003e\n\u003ch2 id=\"the-liskov-substitution-principle\"\u003eThe Liskov Substitution Principle\u003c/h2\u003e\n\u003cp\u003eLiskov\u0026rsquo;s notion of \u0026ldquo;subtype\u0026rdquo; is based on the notion of \u003ca href=\"http://en.wikipedia.org/wiki/Substitutability\" title=\"Substitutability\" target=\"_blank\"\u003esubstitutability\u003c/a\u003e; that is, if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program (e.g., \u003ca href=\"http://en.wikipedia.org/wiki/Correctness\" title=\"Correctness\" target=\"_blank\"\u003ecorrectness\u003c/a\u003e). ie Derived classes must be usable through the base class interface without the need for the user to know the difference\u003c/p\u003e","title":"Design Principles"},{"content":" Bubble Heap Insertion Merge Quick Selection Shell Which sorting algorithm has the best asymptotic runtime complexity? Heap Sort\n","permalink":"https://blog.mckelt.com/articles/posts/sorting-algorithms/","summary":"\u003cul\u003e\n\u003cli\u003eBubble\u003c/li\u003e\n\u003cli\u003eHeap\u003c/li\u003e\n\u003cli\u003eInsertion\u003c/li\u003e\n\u003cli\u003eMerge\u003c/li\u003e\n\u003cli\u003eQuick\u003c/li\u003e\n\u003cli\u003eSelection\u003c/li\u003e\n\u003cli\u003eShell\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"which-sorting-algorithm-has-the-best-asymptotic-runtime-complexity\"\u003eWhich sorting algorithm has the best asymptotic runtime complexity?\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003eHeap Sort\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"628e6d48b76004a4afb95ae28aa2328e\" loading=\"lazy\" src=\"https://user-images.githubusercontent.com/662868/120915766-3509c380-c6d8-11eb-8c96-a4c99e4fd423.png\"\u003e\u003c/p\u003e","title":"Sorting Algorithms"},{"content":" ThreadPool.QueueUserWorkItem(new WaitCallback(LoadUsers)); private void LoadUsers(Object stateInfo) { var site = new SPSite(testHarnessSettings.Url); var web = site.OpenWeb(); foreach(SPUser user in web.AllUsers) { if (usersListBox.InvokeRequired) { usersListBox.Invoke( new MethodInvoker( delegate { usersListBox.Items.Add((user.LoginName)); })); } } ","permalink":"https://blog.mckelt.com/articles/posts/winforms-ui-cross-thread-operations/","summary":"\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003eThreadPool.QueueUserWorkItem(new WaitCallback(LoadUsers));\n\nprivate void LoadUsers(Object stateInfo)\n{\n var site = new SPSite(testHarnessSettings.Url);\n\n var web = site.OpenWeb();\n\n  foreach(SPUser user in web.AllUsers)\n  {\n   if (usersListBox.InvokeRequired)\n   {\n         usersListBox.Invoke(  \n          new MethodInvoker(\n         delegate { usersListBox.Items.Add((user.LoginName));  \n   }));\n  }\n}\n\u003c/code\u003e\u003c/pre\u003e\u003c/blockquote\u003e","title":"Winforms UI cross thread operations"},{"content":"Databases\nSSODB \u0026ndash; Enterprise Single Sign-On database BizTalkRuleEngineDB \u0026ndash; Repository for your business rules BizTalkMsgBoxDb \u0026ndash; Storage for a multitude of BizTalk activities, notably messages BizTalkMgmtDb \u0026ndash; Database for server meta data BizTalkHwsDb \u0026ndash; Human Workflow Services storage database BizTalkEdiDb \u0026ndash; State data for the EDI adapter BizTalkDTADb \u0026ndash; BizTalk tracking engine storage BizTalkStarSchema \u0026ndash; Staging, dimension, and measure tables BAMPrimaryImport \u0026ndash; Raw tracking data for BAM BAMArchive \u0026ndash; Archive for older business activity BAMAlertsNSMain \u0026ndash; Notification services for BAM monitoring BAMAlertsApplication \u0026ndash; Alert information for BAM notifications Orchestration Tools\nGroup\nAllows you to collect various shapes together into a collapsible region, in much the same way that code regions in Visual Studio allow you to collapse code. If your orchestration becomes large and unwieldy, consider organizing items with groups.\nSend\nProvides a mechanism for sending out a message.\nReceive\nProvides a mechanism for receiving a message.\nPort\nProvides the liaison between the BizTalk messages and the orchestration.\nRole Link\nProvides an abstract method of dynamically selecting which of your trading partners you would like to send or receive a message.\nTransform\nAllows you to map a message.\nMessage Assignment\nNested within a Construct Message shape, allows you to create a message and assign values to it.\nConstruct\nMessage Creates a new instance of a message.\nCall Orchestration\nSynchronously calls another BizTalk orchestration. Start Orchestration\nAsynchronously calls another BizTalk orchestration.\nCall Rules\nMakes a call to a business policy.\nExpression\nAllows you to create an “in-line” C#-like language (XLang) coding block that can execute against the message.\nDecide\nAllows you to implement conditional logic in your orchestration flow.\nDelay\nInstructs the orchestration to pause for a set amount of time.\nListen\nProvides a conditional branching mechanism that “listens” for the end of a Delay shape or the input of a message and turns flow control over to the branch that arrives first.\nParallel Actions\nGives you the opportunity to execute shapes in parallel to each other.\nLoop\nProvides a while loop within the orchestration flow.\nScope\nSimilar to coding scope, restricts transactions and error handling to a specified region.\nThrow Exception\nThrows an exception for bubbled-up error handling.\nCompensate\nAllows you to “undo” the effects of a transaction that has run its course by returning or resetting any resources that have been modified.\nSuspend\nFreezes an orchestration and bubbles up an error. While captured by a Suspend shape, the message will become resumable, as needed.\nTerminate\nStops the orchestration and bubbles up an error. The message will be subsequently suspended; however, unlike with the Suspend shape, this message will be not be resumable.\n","permalink":"https://blog.mckelt.com/articles/posts/biztalk-notes/","summary":"\u003cp\u003e\u003cstrong\u003eDatabases\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSSODB \u0026ndash; Enterprise Single Sign-On database\u003c/li\u003e\n\u003cli\u003eBizTalkRuleEngineDB \u0026ndash; Repository for your business rules\u003c/li\u003e\n\u003cli\u003eBizTalkMsgBoxDb \u0026ndash; Storage for a multitude of BizTalk activities, notably messages\u003c/li\u003e\n\u003cli\u003eBizTalkMgmtDb \u0026ndash; Database for server meta data\u003c/li\u003e\n\u003cli\u003eBizTalkHwsDb \u0026ndash; Human Workflow Services storage database\u003c/li\u003e\n\u003cli\u003eBizTalkEdiDb \u0026ndash; State data for the EDI adapter\u003c/li\u003e\n\u003cli\u003eBizTalkDTADb \u0026ndash; BizTalk tracking engine storage\u003c/li\u003e\n\u003cli\u003eBizTalkStarSchema \u0026ndash; Staging, dimension, and measure tables\u003c/li\u003e\n\u003cli\u003eBAMPrimaryImport \u0026ndash; Raw tracking data for BAM\u003c/li\u003e\n\u003cli\u003eBAMArchive \u0026ndash; Archive for older business activity\u003c/li\u003e\n\u003cli\u003eBAMAlertsNSMain \u0026ndash; Notification services for BAM monitoring\u003c/li\u003e\n\u003cli\u003eBAMAlertsApplication \u0026ndash; Alert information for BAM notifications\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eOrchestration Tools\u003c/strong\u003e\u003c/p\u003e","title":"Biztalk notes"},{"content":"The above example uses Windows Communication Foundation (WCF) Integration Facility\nThe main idea here is that WCF should get the service instances from Windsor, which gives us all the usual advantages of IoC plus Windsor\u0026rsquo;s interceptors capabilities. It isn\u0026rsquo;t a lot of code, but it makes it much easier to work with WCF services.\nThe service contains 2 simple methods on the HelloWorld class.\nSayHello \u0026ndash; returns a string \u0026ldquo;Hello World\u0026rdquo; ThrowException \u0026ndash; throws an exception Every single call to each of these is intercepted and logged. Whilst the throw exception will always be caught by the exceptionhandler interceptor.\nThe first project in the solution is the WCF service, whilst the second is just a WPF client tester. The project outlook is as follows:\n","permalink":"https://blog.mckelt.com/articles/posts/wcf-windsor-interceptor-aop-with-logging-and-exception-handler-interceptor/","summary":"\u003cp\u003eThe above example uses Windows Communication Foundation (WCF) Integration Facility\u003c/p\u003e\n\u003cp\u003eThe main idea here is that WCF should get the service instances from Windsor, which gives us all the usual advantages of \u003ca href=\"http://en.wikipedia.org/wiki/Inversion_of_control\" title=\"http://en.wikipedia.org/wiki/Inversion_of_control\" target=\"_blank\"\u003eIoC\u003c/a\u003e \u003cem\u003eplus Windsor\u0026rsquo;s interceptors\u003c/em\u003e capabilities. It isn\u0026rsquo;t a lot of code, but it makes it \u003cem\u003emuch\u003c/em\u003e easier to work with WCF services.\u003c/p\u003e\n\u003cp\u003eThe service contains 2 simple methods on the HelloWorld class.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cul\u003e\n\u003cli\u003eSayHello \u0026ndash; returns a string \u0026ldquo;Hello World\u0026rdquo;\u003c/li\u003e\n\u003cli\u003eThrowException \u0026ndash; throws an exception\u003c/li\u003e\n\u003c/ul\u003e\u003c/blockquote\u003e\n\u003cp\u003eEvery single call to each of these is intercepted and logged.  Whilst the throw exception will always be caught by the exceptionhandler interceptor.\u003c/p\u003e","title":"WCF Windsor Interceptor, AOP with Logging and Exception Handler Interceptor"},{"content":"Running some performance tests using Fitnesse to test the limits of a new Sharepoint DMS solution produced this solution.\nThe code we are trying to test is the AddDocument and the time it takes each call to this to succeed.\nSo we need to add n number of documents to Sharepoint using x number of threads through a WCF service_,_ where n and x are configurable via the Fitnesse wiki\nThe code used to perform the test uses a counting semaphore to kick off x threads which loop while decrementing a volatile variable AddtoDMSXtimes.\npublic string FileName;\npublic int ConcurrentThreads = 10;\npublic volatile int AddtoDMSXtimes = 1000;\nprivate DijkstraSemaphore semaphore; // counting semaphore\nprivate volatile Stack guidStack = new Stack();\npublic volatile List guidList = new List();\nprivate ManualResetEvent resetEvent = new ManualResetEvent(false);\nprivate void Form1_Load(object sender, EventArgs e)\n{\nsemaphore = new DijkstraSemaphore(0, ConcurrentThreads);\n}\nIn the attached example Each loop just counts to 100 and outputs some info as seen below\n(in the real test this was adding a 275KB document to Sharepoint via a new DMSServiceClient().AddGeneratedDocument(dmsDocument, documentContent); call).\nprivate void ExecuteTest()\n{\nConsole.WriteLine(Thread.CurrentThread.Name);\nsemaphore.Release(); while (AddtoDMSXtimes \u0026gt;= 0)\n{\nAddtoDMSXtimes\u0026ndash;;\nguidList.Add(guidStack.Pop());\nfor(int exampleCount=0;exampleCount\u0026lt;100-1;exampleCount++)\n{\nConsole.WriteLine(Thread.CurrentThread.Name + \u0026quot; \u0026quot; + AddtoDMSXtimes.ToString() + \u0026quot; \u0026quot; + exampleCount.ToString()); }\n}\nsemaphore.Acquire();\n}\nInitially new guids were being created in the worker threads \u0026ndash; however I noticed when I had more than multiple threads creating Guids at one time I was getting duplicate guids!\nSo an initial thread is created which branches off and populates a guid stack object with the total number of Guids required.\nWhilst this is off processing the required number of threads is created (x)\nThread populateGuidStackThread = new Thread((ThreadStart) delegate\n{\nfor (int x = 0; x \u0026lt; AddtoDMSXtimes+1; x++)\n{\nguidStack.Push(Guid.NewGuid());\n}\nresetEvent.Set();\n}\n);\npopulateGuidStackThread.Start();\nThe guid creation thread then lets the main thread know it has finished processing and to begin running the worker threads\nOnce it have finished it reports back the total seconds taken to create the threads and total seconds taken for the threads to finish their work.\nThread[] threads = new Thread[ConcurrentThreads];\nStopwatch watch = new Stopwatch();\nwatch.Start();\nint i;\nfor (i = 0; i \u0026lt; ConcurrentThreads; i++)\n{\nthreads[i] = new Thread(new ThreadStart(ExecuteTest));\nthreads[i].Name = \u0026ldquo;Thread \u0026quot; + i.ToString();\n}\nwatch.Stop();\nTimeSpan ts1 = watch.Elapsed;\nif (resetEvent.WaitOne())\n{\nwatch.Start();\nforeach (Thread thread in threads)\n{\nthread.Start();\n}\nwatch.Stop();\n}\nTimeSpan ts2 = watch.Elapsed;\nsemaphore.WaitForStarvation();\nConsole.WriteLine(\u0026rdquo;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026ndash; FINISHED \u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026ndash;\u0026quot;);\nConsole.WriteLine(\u0026ldquo;Time to build threads in seconds \u0026quot; + ts1.TotalSeconds);\nConsole.WriteLine(\u0026ldquo;Time for threads to finish in seconds \u0026quot; + ts2.TotalSeconds);\nCode project class taken from http://www.codeproject.com/KB/recipes/dijkstracountingsemaphore.aspx\n","permalink":"https://blog.mckelt.com/articles/posts/performance-testing-using-a-counting-semaphore-dijkstra/","summary":"\u003cp\u003eRunning some performance tests using Fitnesse to test the limits of a new Sharepoint DMS solution produced this solution.\u003c/p\u003e\n\u003cp\u003eThe code we are trying to test is the AddDocument and the time it takes each call to this to succeed.\u003c/p\u003e\n\u003cp\u003eSo we need to add \u003cem\u003en\u003c/em\u003e number of documents to Sharepoint using \u003cem\u003ex\u003c/em\u003e number of threads through a WCF service_,_ where \u003cem\u003en\u003c/em\u003e and \u003cem\u003ex\u003c/em\u003e are configurable via the Fitnesse wiki\u003c/p\u003e","title":"Performance Testing using a counting semaphore -- Dijkstra"},{"content":"NANT CruiseControl NUnit - How to get unit tests running and displaying on the build server \u0026lt;target name=\u0026quot;webtest\u0026quot; haltonfailure=\u0026quot;false\u0026quot; failonerror=\u0026quot;true\u0026quot;\\\u0026gt; \u0026lt;echo message=\u0026quot;Running unit tests\u0026quot;/\u0026gt; \u0026lt;echo message=\u0026quot;${project.local.folder}\u0026quot;/\u0026gt; \u0026lt;property name=\u0026quot;test\\_dll\\_folder\u0026quot; value\\=\u0026quot;${project.local.folder}\\\\McKelt.Tests\\\\bin\\\\Debug\\\\\u0026quot;/\u0026gt; \u0026lt;exec failonerror=\u0026quot;true\u0026quot; program=\u0026quot;${nunit-console.exe}\u0026quot; workingdir=\u0026quot;${project.local.folder}\u0026quot; verbose=\u0026quot;true\u0026quot; append=\u0026quot;true\u0026quot; commandline=\u0026quot;${test\\_dll\\_folder}McKelt.Tests.dll /xml=${test\\_dll\\_folder}TestResults.xml /output=${test\\_dll\\_folder}TestOutput.txt /err=${test\\_dll\\_folder}TestErrorOutput.txt\u0026quot;\u0026gt; \u0026lt;/exec\u0026gt; \u0026lt;echo message=\u0026quot;-- TEST COMPLETE -- \u0026quot;/\u0026gt; In the following file – c:\\program files\\CruiseControl.Net\\Server\\CCNet.config\n\u0026lt;msbuild\u0026gt; \u0026lt;executable\u0026gt;C:\\WINDOWS\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe\u0026lt;/executable\u0026gt; \u0026lt;workingDirectory\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\\u0026lt;/workingDirectory\u0026gt; \u0026lt;projectFile\u0026gt;McKeltOnlineForms.sln\u0026lt;/projectFile\u0026gt; \u0026lt;buildArgs\u0026gt; /noconsolelogger /p:Configuration=Debug /v:quiet \u0026lt;/buildArgs\u0026gt; \u0026lt;targets\u0026gt;Rebuild\u0026lt;/targets\u0026gt; \u0026lt;timeout\u0026gt;120\u0026lt;/timeout\u0026gt; \u0026lt;logger\u0026gt;c:\\Program Files\\CruiseControl.NET\\server\\Rodemeyer.MsBuildToCCNet.dll\u0026lt;/logger\u0026gt; \u0026lt;/msbuild\u0026gt; \u0026lt;/tasks\u0026gt; \u0026lt;publishers\u0026gt; \u0026lt;merge\u0026gt; \u0026lt;files\u0026gt; \u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Web.Application.Tests\\bin\\Debug\\testresults.xml\u0026lt;/file\u0026gt; \u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Service.Implementations.Tests\\bin\\Debug\\testresults.xml\u0026lt;/file\u0026gt; \u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\Tests\\AcceptanceTests\\bin\\Debug\\TestResults.xml\u0026lt;/file\u0026gt; \u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Web.Application.Tests\\bin\\Debug\\*Output.txt\u0026lt;/file\u0026gt; \u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Service.Implementations.Tests\\bin\\Debug\\*Output.txt\u0026lt;/file\u0026gt; \u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\Tests\\AcceptanceTests\\bin\\Debug\\*Output.txt\u0026lt;/file\u0026gt; \u0026lt;/files\u0026gt; \u0026lt;/merge\u0026gt; \u0026lt;/publishers\u0026gt;\nIn your dashboard.config\n\u0026lt;?xml version\\=\u0026quot;1.0\u0026quot; encoding\\=\u0026quot;utf-8\u0026quot;?\\\u0026gt; \u0026lt;dashboard\u0026gt; \u0026lt;remoteServices\u0026gt; \u0026lt;servers\u0026gt;\n\u0026lt;server name=\u0026ldquo;local\u0026rdquo; url=\u0026ldquo;tcp://localhost:21234/CruiseManager.rem\u0026rdquo; allowForceBuild=\u0026ldquo;true\u0026rdquo; allowStartStopBuild=\u0026ldquo;true\u0026rdquo; backwardsCompatible=\u0026ldquo;false\u0026rdquo; /\u0026gt;\n\u0026lt;/servers\u0026gt; \u0026lt;/remoteServices\u0026gt; \u0026lt;xslFileNames\u0026gt;\n\u0026lt;xslFile\u0026gt;xsl\\header.xsl\u0026lt;/xslFile\u0026gt;\n\u0026lt;xslFile\u0026gt;xsl\\msbuild2ccnet.xsl\u0026lt;/xslFile\u0026gt;\n\u0026lt;xslFile\u0026gt;xsl\\modifications.xsl\u0026lt;/xslFile\u0026gt;\n\u0026lt;xslFile\u0026gt;xsl\\unittests.xsl\u0026lt;/xslFile\u0026gt;\n\u0026lt;/xslFileNames\u0026gt; \u0026lt;/buildReportBuildPlugin\u0026gt; \u0026lt;xslReportBuildPlugin description=\u0026ldquo;NAnt Output\u0026rdquo; actionName=\u0026ldquo;NAntOutputBuildReport\u0026rdquo; xslFileName=\u0026ldquo;xsl\\NAnt.xsl\u0026rdquo;\u0026gt;\u0026lt;/xslReportBuildPlugin\u0026gt;\n\u0026lt;xslReportBuildPlugin description=\u0026ldquo;NAnt Timings\u0026rdquo; actionName=\u0026ldquo;NAntTimingsBuildReport\u0026rdquo; xslFileName=\u0026ldquo;xsl\\NAntTiming.xsl\u0026rdquo;\u0026gt;\u0026lt;/xslReportBuildPlugin\u0026gt;\n\u0026lt;xslReportBuildPlugin description=\u0026ldquo;NUnit Details\u0026rdquo; actionName=\u0026ldquo;NUnitDetailsBuildReport\u0026rdquo; xslFileName=\u0026ldquo;xsl\\tests.xsl\u0026rdquo;\u0026gt;\u0026lt;/xslReportBuildPlugin\u0026gt;\n\u0026lt;xslReportBuildPlugin description=\u0026ldquo;NUnit Timings\u0026rdquo; actionName=\u0026ldquo;NUnitTimingsBuildReport\u0026rdquo; xslFileName=\u0026ldquo;xsl\\timing.xsl\u0026rdquo;\u0026gt;\u0026lt;/xslReportBuildPlugin\u0026gt;\n\u0026lt;/buildPlugins\u0026gt; \u0026lt;securityPlugins\u0026gt; \u0026lt;/securityPlugins\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/dashboard\u0026gt;\n","permalink":"https://blog.mckelt.com/articles/posts/nant-cruisecontrol-nunit-how-to-get-unit-tests-running-and-displaying-on-the-build-server/","summary":"\u003ch2 id=\"nant-cruisecontrol-nunit-----how-to-get-unit-tests-running-and-displaying-on-the-build-server\"\u003eNANT CruiseControl NUnit   - How to get unit tests running and displaying on the build server\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026lt;target name=\u0026quot;webtest\u0026quot; haltonfailure=\u0026quot;false\u0026quot; failonerror=\u0026quot;true\u0026quot;\\\u0026gt;\n\u0026lt;echo message=\u0026quot;Running unit tests\u0026quot;/\u0026gt;\n    \u0026lt;echo message=\u0026quot;${project.local.folder}\u0026quot;/\u0026gt;\n    \u0026lt;property name=\u0026quot;test\\_dll\\_folder\u0026quot; value\\=\u0026quot;${project.local.folder}\\\\McKelt.Tests\\\\bin\\\\Debug\\\\\u0026quot;/\u0026gt;\n    \u0026lt;exec failonerror=\u0026quot;true\u0026quot; program=\u0026quot;${nunit-console.exe}\u0026quot; workingdir=\u0026quot;${project.local.folder}\u0026quot; verbose=\u0026quot;true\u0026quot; append=\u0026quot;true\u0026quot; commandline=\u0026quot;${test\\_dll\\_folder}McKelt.Tests.dll /xml=${test\\_dll\\_folder}TestResults.xml /output=${test\\_dll\\_folder}TestOutput.txt /err=${test\\_dll\\_folder}TestErrorOutput.txt\u0026quot;\u0026gt;\n\u0026lt;/exec\u0026gt;\n\u0026lt;echo message=\u0026quot;-- TEST COMPLETE -- \u0026quot;/\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/target\u003e\u003c/blockquote\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cp\u003eIn the following file – c:\\program files\\CruiseControl.Net\\Server\\CCNet.config\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e     \u0026lt;msbuild\u0026gt;\n\u0026lt;executable\u0026gt;C:\\WINDOWS\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe\u0026lt;/executable\u0026gt;\n\u0026lt;workingDirectory\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\\u0026lt;/workingDirectory\u0026gt;\n\u0026lt;projectFile\u0026gt;McKeltOnlineForms.sln\u0026lt;/projectFile\u0026gt;\n\u0026lt;buildArgs\u0026gt; /noconsolelogger /p:Configuration=Debug /v:quiet \u0026lt;/buildArgs\u0026gt;\n\u0026lt;targets\u0026gt;Rebuild\u0026lt;/targets\u0026gt;\n\u0026lt;timeout\u0026gt;120\u0026lt;/timeout\u0026gt;\n\u0026lt;logger\u0026gt;c:\\Program Files\\CruiseControl.NET\\server\\Rodemeyer.MsBuildToCCNet.dll\u0026lt;/logger\u0026gt;\n\u0026lt;/msbuild\u0026gt;\n\u0026lt;/tasks\u0026gt;\n\u0026lt;publishers\u0026gt;\n\u0026lt;merge\u0026gt;\n\u0026lt;files\u0026gt;\n\u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Web.Application.Tests\\bin\\Debug\\testresults.xml\u0026lt;/file\u0026gt;\n\u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Service.Implementations.Tests\\bin\\Debug\\testresults.xml\u0026lt;/file\u0026gt;\n\u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\Tests\\AcceptanceTests\\bin\\Debug\\TestResults.xml\u0026lt;/file\u0026gt;\n\u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Web.Application.Tests\\bin\\Debug\\*Output.txt\u0026lt;/file\u0026gt;\n\u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\McKelt.Service.Implementations.Tests\\bin\\Debug\\*Output.txt\u0026lt;/file\u0026gt;\n\u0026lt;file\u0026gt;C:\\CCWorking\\McKeltOnlineForms\\CodeBase\\Tests\\AcceptanceTests\\bin\\Debug\\*Output.txt\u0026lt;/file\u0026gt;\n\u0026lt;/files\u0026gt;\n\u0026lt;/merge\u0026gt;\n\u003cxmllogger/\u003e\n\u0026lt;/publishers\u0026gt;\u003c/p\u003e","title":"NANT CruiseControl NUnit   - How to get unit tests running and displaying on the build server"},{"content":"SharePoint main objects\nSPSite = Site; Collection SPWeb = Site Web; SPSite siteCollection = new SPSite(\u0026quot;http://localhost/sites/sitename\u0026quot;); SPWeb web = siteCollection.OpenWeb(); Features\nFeatures define a mechanism for defining site elements and adding them to a target site or site collection through a process called feature activation\nAn example feature\n\u0026lt;Feature Id=\u0026ldquo;6AA03A00-02B5-4d83-A041-1CEB0DE9EF9E\u0026rdquo; Title=\u0026ldquo;Chris Document Manager\u0026rdquo; Description=\u0026ldquo;Test description\u0026rdquo; Version=\u0026ldquo;1.0.0.0\u0026rdquo; Scope=\u0026ldquo;Web\u0026rdquo; ImageUrl=\u0026ldquo;TestImage.gif\u0026rdquo; ReceiverAssembly=\u0026ldquo;DocumentManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=52cb0cd67d773ef7\u0026rdquo; ReceiverClass=\u0026ldquo;DocumentManager.FeatureReceiver\u0026rdquo; xmlns=\u0026ldquo;http://schemas.microsoft.com/sharepoint/\"\u0026gt; \u0026lt;ElementManifests\u0026gt; \u0026lt;ElementManifest Location=\u0026ldquo;elements.xml\u0026rdquo; /\u0026gt; \u0026lt;/ElementManifests\u0026gt; \u0026lt;/Feature\u0026gt;\nElements\nThe element types that can be defined by a feature include\nMenu commands Link commands Pages templates Page instances List definitions List instances Event handlers Workflows \u0026lt;Elements xmlns=\u0026ldquo;http://schemas.microsoft.com/sharepoint/\"\u0026gt; \u0026lt;CustomAction Id=\u0026ldquo;SiteActionsToolbar\u0026rdquo; GroupId=\u0026ldquo;SiteActions\u0026rdquo; Location=\u0026ldquo;Microsoft.SharePoint.StandardMenu\u0026rdquo; Sequence=\u0026ldquo;100\u0026rdquo; Title=\u0026ldquo;Hello World\u0026rdquo; Description=\u0026ldquo;A custom menu item added using a feature\u0026rdquo; ImageUrl=\u0026rdquo;_layouts/images/crtsite.gif\u0026rdquo; \u0026gt; \u0026lt;UrlAction Url=\u0026ldquo;http://msdn.microsoft.com\u0026rdquo;/\u0026gt; \u0026lt;/CustomAction\u0026gt; \u0026lt;/Elements\u0026gt;\nConfiguration Elements\n\u0026lt;configuration\u0026gt; \u0026lt;configSections\u0026gt; \u0026lt;sectionGroup name=\u0026ldquo;SharePoint\u0026rdquo;\u0026gt; \u0026lt;section name=\u0026ldquo;SafeControls\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;RuntimeFilter\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;WebPartLimits\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;WebPartCache\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;WebPartWorkItem\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;WebPartControls\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;SafeMode\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;MergedActions\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;PeoplePickerWildCards\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;SafeControls\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;section name=\u0026ldquo;SafeControls\u0026rdquo; type=\u0026quot;\u0026quot;/\u0026gt; \u0026lt;/sectionGroup\u0026gt; \u0026lt;/configSections\u0026gt; \u0026lt;SharePoint\u0026gt; \u0026lt;/SharePoint\u0026gt; \u0026lt;/configuration\u0026gt;\nSPVirtualPathProvider\nSPVirtualPathProvider allows files to be stored in the database – a term referred to as ‘ung_hosted_’\nIt can also retrieve pages from the file system ‘G_hosted_’ and pass them to the asp.net aspx page parser\nPages Types\nSite Pages\nSupport customisation Have web parts and webpart zones Application Pages\nDeployed as physical files (aspx) of the front end web server in the following location C: \\program files \\common files \\microsoft shared \\web server extensions \\12 \\template \\layouts Inherit from LayoutsPageBase Debugging WSS Components\n\u0026lt;configuration\u0026gt; \u0026lt;SharePoint\u0026gt; \u0026lt;SafeMode CallStack=\u0026ldquo;true\u0026rdquo;/\u0026gt; \u0026lt;/SharePoint\u0026gt; \u0026lt;system.web\u0026gt; \u0026lt;customErrors mode=\u0026ldquo;Off\u0026rdquo;/\u0026gt; \u0026lt;compilation debug=\u0026ldquo;true\u0026rdquo;/\u0026gt; \u0026lt;/system.web\u0026gt; \u0026lt;/configuration\u0026gt;\nSPFile\nSPWeb site = SPContext.Current.Web; SPFile homePage = site.GetFile(“default.aspx”)\nDefault.master\nResides in c: \\program files \\common files \\microsoft shared \\web server extensions \\12 \\template \\global \\default.master\nWeb Part Gallery\nDocument library that contains serialised web parts. There web parts have a .webpart extension (older WSS 2.0 were serialised using an old version with a .dwp extension)\nEditor Web Part has 2 abstract methods to override to implement changes – ApplyChanges \u0026amp; SynchChanges\nIWebPartField interface is implemented by many WSS web parts \u0026ndash; ie List View \u0026amp; Image\nHTTPHandler endpoints are the preferred data source for AJAX applications in which data is returned in a simple XML, text or JSON format representing the data query. This is a subset of the REST architecture pattern (Representational State Transfer).\nIHttpAsynchHandler is the preferred interface for handlers that need long running tasks.\nLists \u0026amp; Content Types\nThe create page contains built in list types broken out into sections including libraries, communications, tracking and custom lists\nWSS List definitions\nDocument library Form library Wiki page library Picture library Announcements Contacts Discussions Links Calendar Tasks Project tasks Issue tracking Custom list WSS list bast types\nStandard lists = 0 Document libraries = 1 Discussion forums = 3 Vote/Survey lists = 4 Issue lists = 5 Lists store their data in columns (also called fields). WSS 3.0 introduces site columns which are reusable fields\nTo have a custom field type recognised a Field Schema file is added in a CAML based syntax into a well known location.\nField types are defined in files name fldtypes_companyName.xml that must be deployed in TEMPLATE\\XML directory\nSPQuery query = new SPQuery(); query.ViewFields = @\u0026quot;\u0026quot;; query.Query = @\u0026quot; \u0026quot;; //NB:// SPQuery object returns a SPListItemCollection || SPSiteDataQuery returns a datatable\nThe built in columns are defined in the build-in fields feature\nContent Types \u0026mdash;\u0026gt; Content Type Ids\nContent types define underlying schema for either an item oin a list or a document in a document library.\nContent types are either list based or document based.\nA forms library is designed to store XML documents created from InfoPath forms.\nA schema file must define content type references and its own separate data scheme as well as views and forms.\nCreate a custom document library in code \u0026ndash; with 4 extended fields\nconst string LIBRARY_NAME = \u0026ldquo;TradeDocumentLibrary\u0026rdquo;;\nSPSite siteCollection = new SPSite(\u0026ldquo;http://localhost:334\u0026rdquo;);\nSPWeb web = siteCollection.OpenWeb();\nif (!ListExists(web.Lists, LIBRARY_NAME)) {\nGuid listId = siteCollection.RootWeb.Lists.Add(LIBRARY_NAME, \u0026ldquo;Beazley Trade Document Library\u0026rdquo;, SPListTemplateType.DocumentLibrary);\nSPList list = web.Lists\\ [listId];\nlist.Fields.Add(\u0026ldquo;BTProductId\u0026rdquo;, SPFieldType.Number, true);\nlist.Fields.Add(\u0026ldquo;BTDocumentVersionNo\u0026rdquo;, SPFieldType.Number, true);\nlist.Fields.Add(\u0026ldquo;BTProductName\u0026rdquo;, SPFieldType.Text, false);\nlist.Fields.Add(\u0026ldquo;TemplateType\u0026rdquo;, SPFieldType.Text, false);\nSPField btProductIdField = list.Fields\\ [\u0026ldquo;BTProductId\u0026rdquo;];\nbtProductIdField.ShowInDisplayForm = true;\nbtProductIdField.ShowInEditForm = true;\nbtProductIdField.ShowInListSettings = true;\nbtProductIdField.ShowInNewForm = true;\nbtProductIdField.ShowInViewForms = true;\nSPView defaultView = list.Views\\ [0];\ndefaultView.ViewFields.Add(btProductIdField);\ndefaultView.Update();\nlist.ContentTypesEnabled = false;\nlist.OnQuickLaunch = true;\nlist.EnableAttachments = false;\nlist.EnableVersioning = false;\nlist.NoCrawl = true;\nlist.Update();\n}\nOffice Open XML\nOffice Open XML file formats. Top level file such as Hello.docx is know as a package.\nInside a package are 2 kinds of internal components: parts and items\nIn general, parts contain content and items contain metadata describing the parts.\nItems can be further subdivided into relationship items and content-type items\nA part is an internal component containing content that is presisted inside the package.\nThe majority of parts are simple text files serialised as XML with an associated schema.\nOpen office xml file formats use relationships to define associations between a source and a target part.\nA package relationship defines an association between the top level package and a part.\nA part relationship defines an association between a parent part and a child part.\nSite definition \u0026ndash; is the top level component in WSS that aggregates smaller, more modular definitions to create a complete site template that can be used to provision sites.\nSite definitions are deployed within the 12\\TEMPLATE\\SITETEMPLATES directory and are referenced in the 12\\TEMPLATE\\\\XML directory WEBTEMP.XML files where the folder is the locale identifier 12\\TEMPLATE\\1033\\XML for US English\nGlobal site definitio - provides a common repository for site provision instructions required by every site definition.\nThe ONET.xml file serves as a high level manifest for the site definition and references the components that are to be used A feature can also be used to attach one or more other features to a site definition through a technique called feature stapling Localisation in WSS is based on language packs that are deployed as solutions packages\nA _solution package_is a compressed .cab file with a .wsp extension containing the componentsto be deployed on a target web server. The .wsp file for a solutions package can be built using the MAKECAB operations system utility by reading the definition from a .ddf file.\nThe .ddf file defines the output structure of the .wsp file by referencing each file in its source location and its destination location in the .wsp file.\nThe metadata for a solution package is maintained in a file named manifest.xml that must be added to the root of the .wsp file. It is the manifest.xml that tells the WSS runtime which template files to copy into the WSS system directories.\nWSS permission definitions\nEnvironment permission Security Permission AspNetHostingPermission WebPermission SPSecurity allows code to run with higher priviledges\nSPSecurity.RunWithElevitedPrivaledges(delegate{// code run as SharePoint\\\\System}) ","permalink":"https://blog.mckelt.com/articles/posts/windows-sharepoint-services-notes/","summary":"\u003cp\u003e\u003cstrong\u003eSharePoint main objects\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eSPSite = Site;  \nCollection SPWeb = Site Web;  \nSPSite siteCollection = new SPSite(\u0026quot;http://localhost/sites/sitename\u0026quot;);      SPWeb web = siteCollection.OpenWeb();\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eFeatures\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eFeatures define a mechanism for defining site elements and adding them to a target site or site collection through a process called \u003cem\u003efeature activation\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eAn example feature\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e \u0026lt;Feature Id=\u0026ldquo;6AA03A00-02B5-4d83-A041-1CEB0DE9EF9E\u0026rdquo; Title=\u0026ldquo;Chris Document Manager\u0026rdquo; Description=\u0026ldquo;Test description\u0026rdquo; Version=\u0026ldquo;1.0.0.0\u0026rdquo;  Scope=\u0026ldquo;Web\u0026rdquo; ImageUrl=\u0026ldquo;TestImage.gif\u0026rdquo; ReceiverAssembly=\u0026ldquo;DocumentManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=52cb0cd67d773ef7\u0026rdquo; ReceiverClass=\u0026ldquo;DocumentManager.FeatureReceiver\u0026rdquo; xmlns=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/sharepoint/%22\" target=\"_blank\"\u003ehttp://schemas.microsoft.com/sharepoint/\"\u003c/a\u003e\u0026gt; \u0026lt;ElementManifests\u0026gt; \u0026lt;ElementManifest Location=\u0026ldquo;elements.xml\u0026rdquo; /\u0026gt; \u0026lt;/ElementManifests\u0026gt; \u0026lt;/Feature\u0026gt;\u003c/p\u003e","title":"Windows SharePoint Services Notes"},{"content":"Here is a quick example of how to use DB Deploy\nThis example uses NANT to run DBDeploy which in turn generates the output.sql file. This is then run against the database causing our changes to be run in and putting an entry in the ChangeLog table to tell you which sql files have been run.\nTo run this sample\nDownload to a location on your computer e.g. C:\\Examples\\DBDeployExample Create a database onyour localhost called DBDeployExample In a command prompt (Or PowerShell) use NANT to build the solution \u0026ndash;(I have this setup as an environment variable setup and simply type \u0026lsquo;NANT\u0026rsquo;) NANT will build the default.build file and run the database changes Opening the solution file looks like this\nSetup DB Deploy change tables The ChangeLog table in the database is used by DBDeploy for change management and will look like this:\nThe default.build file contains a target that actions DBDeploy\n\u0026lt;target name=\u0026ldquo;script.generate\u0026rdquo; description=\u0026ldquo;generate a sql upgrade script\u0026rdquo;\u0026gt; \u0026lt;call target=\u0026ldquo;setup.changelogtable\u0026rdquo;/\u0026gt; \u0026lt;call target=\u0026ldquo;setup.builddir\u0026rdquo;/\u0026gt; \u0026lt;echo message=\u0026ldquo;Calling dbdeploy with dbConnection=${connstring}\u0026hellip;\u0026rdquo; /\u0026gt; \u0026lt;dbdeploy dbType=\u0026ldquo;mssql\u0026quot;dbConnection=\u0026quot;${connstring}\u0026rdquo; dir=\u0026quot;${script.dir}\u0026gt; outputFile=\u0026quot;${output.file}\u0026quot; undoOutputFile=\u0026quot;${undo.output.file}\u0026quot; /\u0026gt;\n\u0026lt;echo message=\u0026quot;\u0026hellip;finished calling dbdeploy.\u0026quot; /\u0026gt;\nThe output file contains all change files found on the file system that are not contained in the ChangeLog table\nThe following command runs the output script against the database\n\u0026lt;target name=\u0026ldquo;script.execute\u0026rdquo;\u0026gt;\n\u0026lt;echo message=\u0026ldquo;Executing script ${script.execute.filename} against database ${database.name}\u0026hellip;\u0026rdquo; /\u0026gt; \u0026lt;exec program=\u0026quot;${sqlcmd}\u0026quot;\u0026gt;\n\u0026lt;arg value=\u0026quot;${script.execute.extraparams}\u0026quot; /\u0026gt; \u0026lt;arg value=\u0026quot;-i\u0026quot; /\u0026gt; \u0026lt;arg value=\u0026quot;${script.execute.filename}\u0026quot; /\u0026gt; \u0026lt;arg value=\u0026quot;-d\u0026quot; /\u0026gt;\n\u0026lt;arg value=\u0026quot;${database.name}\u0026quot; /\u0026gt;\n\u0026lt;arg value=\u0026quot;-S\u0026quot;/\u0026gt;\n\u0026lt;arg value=\u0026quot;${server}\u0026quot; /\u0026gt;\n\u0026lt;/exec\u0026gt;\n\u0026lt;echo message=\u0026quot;\u0026hellip;finished executing script.\u0026quot; /\u0026gt;\n\u0026lt;/target\u0026gt;\nOutput SQL change scripts are executed against the DB \u0026amp; recorded in the DBDeploy table\n","permalink":"https://blog.mckelt.com/articles/posts/how-to-use-db-deploy/","summary":"\u003cp\u003eHere is a quick example of how to use \u003ca href=\"http://dbdeploy.com/\" title=\"http://dbdeploy.com/\" target=\"_blank\"\u003eDB Deploy\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThis example uses NANT to run DBDeploy which in turn generates the \u003cem\u003eoutput.sql\u003c/em\u003e file.  This is then run against the database causing our changes to be run in and putting an entry in the ChangeLog table to tell you which sql files have been run.\u003c/p\u003e\n\u003cp\u003eTo run this sample\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eDownload to a location on your computer e.g. \u003cem\u003eC:\\Examples\\DBDeployExample\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eCreate a database onyour localhost called \u003cem\u003eDBDeployExample\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eIn a command prompt (Or \u003ca href=\"http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx\" title=\"http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx\" target=\"_blank\"\u003ePowerShell\u003c/a\u003e) use \u003ca href=\"http://nant.sourceforge.net/\" title=\"http://nant.sourceforge.net/\" target=\"_blank\"\u003eNANT\u003c/a\u003e to build the solution \u0026ndash;(I have this setup as an environment variable setup and simply type \u0026lsquo;NANT\u0026rsquo;)\u003c/li\u003e\n\u003cli\u003eNANT will build the default.build file and run the database changes\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eOpening the solution file looks like this\u003c/p\u003e","title":"How to use DB Deploy"},{"content":"Introduction Here is a simple example of how to use fake repositories in test driven development.\nBy using Fake Repositories generated from a binary file we are able to quickly use \u0026lsquo;real data\u0026rsquo; in all our tests.\nIt is a Visual Studio 2008 solution and uses the Castle project\u0026rsquo;s Active Record as an ORM.\nStep 1 – Our Core Model The model will consist of 3 classes\n- SuperHero e.g. Superman - SupeHeroId - RealName - SuperHeroName - Power e.g. Flight - PowerId - PowerName - SuperHeroPower e.g. Superman’s flight - SuperHeroPowerId - Comments (e.g. Faster than a speeding bullet) Each of our classes implements an Interface called IIdRetriever\n/// \u0026lt;summary\u0026gt; /// This was created so that the BaseRepositoryFake class can provide a standard /// implementation for fake repositories despite not knowing what property holds /// the Id. /// \u0026lt;/summary\u0026gt; public interface IIdRetriever { int GetId(); void SetId(int id); } First we define a base interface that defines all our methods needed for an ‘in-memory’ database\nThis base interface is called IRepository\npublic interface IRepository\u0026lt;T\u0026gt; where T : class { T Save(T item); T SaveOrUpdate(T item); T Get(objectid); long Count(); ICollection\u0026lt;T\u0026gt; FindAll(params ICriterion[] criteria); void Delete(T item); } Now for each class we need a repository so we define 3 repository interfaces that implement the IRepository interface with their corresponding class\nISuperHeroRepository\nIPowerRepository\nISuperHeroPowerRepository\npublic interface ISuperHeroRepository : IRepository{}\nNow for the concrete implementations of our repositories the following classes are created\nSuperHeroRepository\nPowerRepository\nSuperHeroPowerRepository\npublic class PowerRepository : ARRepository, IPowerRepository{}\nStep 2 – Create the database, populate data and generate the binary file In the attached project there is a command line utility project that accepts 3 arguments\nCreateSchema – will create the tables in the designated database in the app.config PopulateData – will populate the tables with some sample data GenerateBinary – will get our ‘core’ object which contains relations to all our data and binary serialize it into a file Step 3 – Creating our fakes for use in tests We will now create fake ‘in-memory’ repositories which use the pre-populated binary data for use in out tests\nFirstly there are some integration tests in the database which ensure the add/edit behaviour is correct when talking to the database.\nSecondly there is a folder entitled Fakes\nThe main file here is the BaseRepositoryFake which contains all our base methods to mimic a database – yet in memory through an internal collection.\nBy inheriting this class our other fake repositories get the ability to Save,SaveOrUpdate,Delete and find all.\nOur inheriting fake repositories are as follows\nSuperHeroPowerRepositoryFake PowerHeroRepositoryFake SuperHeroPowerRepositoryFake These simply inherit the BaseRepositoryFake and implement their corresponding interface\npublic class SuperHeroRepositoryFake : BaseRepositoryFake\u0026lt;SuperHero\u0026gt;, ISuperHeroRepository An explanation of the files in the root of the Tests project\nActiveRecordFixture – singleton one time setup for active record RandomHelper – Set Ids and values for our fake objects (As SQL Server identity columns these will be seeded in the DB) SeededRepositoryFakes – contains a fake representation of each repository (e.g. SuperHeroRepository) – data is read from the binary file in these SeededRepositoryFakesCountTest – test to ensure the SeededRepositoryFakes are filled SuperHeroSeed – class that reads from the binary file ","permalink":"https://blog.mckelt.com/articles/posts/active-record-and-fake-in-memory-repositories-in-test-driven-development/","summary":"\u003ch3 id=\"introduction\"\u003eIntroduction\u003c/h3\u003e\n\u003cp\u003eHere is a simple example of how to use fake repositories in test driven development.\u003c/p\u003e\n\u003cp\u003eBy using Fake Repositories generated from a binary file we are able to quickly use \u0026lsquo;real data\u0026rsquo; in all our tests.\u003c/p\u003e\n\u003cp\u003eIt is a Visual Studio 2008 solution and uses the Castle project\u0026rsquo;s \u003ca href=\"http://www.castleproject.org/\" title=\"http://www.castleproject.org/\" target=\"_blank\"\u003eActive Record\u003c/a\u003e as an ORM.\u003c/p\u003e\n\u003ch3 id=\"step-1--our-core-model\"\u003eStep 1 – Our Core Model\u003c/h3\u003e\n\u003cp\u003eThe model will consist of 3 classes\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e- SuperHero e.g. Superman\n    - SupeHeroId\n    - RealName\n    - SuperHeroName\n- Power e.g. Flight\n    - PowerId\n    - PowerName\n- SuperHeroPower e.g. Superman’s flight\n    - SuperHeroPowerId\n    - Comments (e.g. Faster than a speeding bullet)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eEach of our classes implements an Interface called \u003cem\u003eIIdRetriever\u003c/em\u003e\u003c/p\u003e","title":"Active Record and Fake In Memory Repositories in Test Driven Development"},{"content":"Delete all tables EXEC sp_MSforeachtable @command1 = \u0026ldquo;DROP TABLE ?\u0026rdquo;\nGrant execute permissions to all stored procedures to a specific user `CREATE PROC grantexecutepermission( @UserName NVARCHAR(250)) AS DECLARE curse CURSOR FOR SELECT name FROM sysobjects WHERE TYPE = 'P'` OPEN curse DECLARE @proc VARCHAR(100) DECLARE @stmt NVARCHAR(200) FETCH NEXT FROM curse INTO @proc WHILE @@FETCH\\_STATUS \\= 0 BEGIN SET @stmt \\= 'grant execute on ' + @proc + ' to ' + @UserName EXEC sp\\_executesql @STMT PRINT @stmt FETCH NEXT FROM curse INTO @proc END CLOSE curse DEALLOCATE curse Check if column exists before adding IF NOT EXISTS (select \\* from Information\\_SCHEMA.columns WHERE Table\\_name='ExampleTable' and column\\_name='ExampleColumn') BEGIN ALTER TABLE ExampleTable ADD ExampleColumn nvarchar(350) END Use a cursor to print out column values to a pre-formatted string SET NOCOUNT ON DECLARE @BTDocumentId int DECLARE @BTDocumentVersionNo int DECLARE myCursor CURsOR FOR SELECT Id as BTDocumentId, VersionNo as BTDocumentVersionNo from document where istemplate = 1 OPEN myCursor FETCH NEXT FROM myCursor INTO @BTDocumentId, @BTdocumentVersionNo WHILE @@FETCH\\_STATUS = 0 BEGIN PRINT 'BTVersionId=' + CAST(@BTDocumentId AS VARCHAR(500)) + ' AND BTDocumentVersionNo=' + CAST(@BTDocumentVersionNo AS VARCHAR(500)) + ', ' FETCH NEXT FROM myCursor INTO @BTDocumentId, @BTdocumentVersionNo END CLOSE myCursor DEALLOCATE myCursor Reseed a table DBCC CHECKIDENT (\u0026quot;Risk\u0026quot;, RESEED, 920617); Drop column – remove foreign key reference first IF EXISTS(SELECT \\* FROM INFORMATION\\_SCHEMA.TABLE\\_CONSTRAINTS WHERE CONSTRAINT\\_SCHEMA='dbo' AND CONSTRAINT\\_NAME='FK\\_Coverage\\_CobCode' AND TABLE\\_NAME='Coverage') BEGIN ALTER TABLE dbo.Coverage DROP CONSTRAINT FK\\_Coverage\\_CobCode; END IF EXISTS (select \\* from Information\\_SCHEMA.columns WHERE Table\\_name='Coverage' and column\\_name='CobCodeId') BEGIN ALTER TABLE Coverage DROP COLUMN CobCodeId END CSV import IF Object _id('tempdb..#csv') IS NOT NULL DROP TABLE #csv CREATE TABLE #csv ( positionId NVARCHAR(150) COLLATE sql_latin1_general_cp1_ci_as, salesforceno NVARCHAR(150) COLLATE sql_latin1_general_cp1_ci_as, ) DECLARE @FileName NVARCHAR (450) SET @FileName ='C:\\\\Temp\\\\DATA.tab' DECLARE @SqlStatement NVARCHAR(4000) SET @SqlStatement = ' BULK INSERT #csv FROM ''' + @FileName + ''' WITH ( FIELDTERMINATOR = ''\\\\t'', ROWTERMINATOR = ''\\\\n'' ) ' EXEC Sp\\_executesql @SqlStatement DECLARE @Total INT SET @Total = (SELECT Count(positionId) FROM #csv) PRINT 'Total Imported Rows' PRINT @Total \\-- CHANGE to your DB database ----------------- use YourDB DECLARE @Id NVARCHAR(150) DECLARE @SfId NVARCHAR(150) WHILE (SELECT Count(\\*) FROM #csv) \u0026gt; 0 BEGIN SELECT TOP 1 @Id = positionId, @SfId = salesforceno FROM #csv UPDATE useraccount SET positionId = @SfId WHERE positionId = @Id PRINT 'OLD AdviserNo = ' PRINT @Id PRINT 'NEW SalesForce PositionId =' PRINT @SfId DELETE #csv WHERE positionId = @Id END Delete all objects in the database DECLARE @Sql NVARCHAR(500) DECLARE @Cursor CURSOR SET @Cursor = CURSOR FAST_FORWARD FOR SELECT DISTINCT sql = \u0026#39;ALTER TABLE [\u0026#39; + tc2.TABLE_NAME + \u0026#39;] DROP [\u0026#39; + rc1.CONSTRAINT_NAME + \u0026#39;]\u0026#39; FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1 LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME =rc1.CONSTRAINT_NAME OPEN @Cursor FETCH NEXT FROM @Cursor INTO @Sql WHILE (@@FETCH_STATUS = 0) BEGIN Exec SP_EXECUTESQL @Sql FETCH NEXT FROM @Cursor INTO @Sql END CLOSE @Cursor DEALLOCATE @Cursor GO EXEC sp_MSForEachTable \u0026#39;DROP TABLE ?\u0026#39; GO ","permalink":"https://blog.mckelt.com/articles/posts/sql-tricks/","summary":"\u003ch4 id=\"delete-all-tables\"\u003eDelete all tables\u003c/h4\u003e\n\u003cp\u003eEXEC sp_MSforeachtable @command1 = \u0026ldquo;DROP TABLE ?\u0026rdquo;\u003c/p\u003e\n\u003ch4 id=\"grant-execute-permissions-to-all-stored-procedures-to-a-specific-user\"\u003eGrant execute permissions to all stored procedures to a specific user\u003c/h4\u003e\n\u003cpre\u003e\u003ccode\u003e`CREATE PROC grantexecutepermission( @UserName NVARCHAR(250)) AS DECLARE curse CURSOR  FOR SELECT name FROM   sysobjects WHERE  TYPE = 'P'`\n\nOPEN curse \nDECLARE  @proc VARCHAR(100) \nDECLARE  @stmt NVARCHAR(200) \nFETCH NEXT FROM curse INTO @proc \nWHILE @@FETCH\\_STATUS \\= 0 BEGIN SET @stmt \\= 'grant execute on ' + @proc + ' to ' + @UserName\n\nEXEC sp\\_executesql @STMT\nPRINT @stmt\n\nFETCH NEXT FROM curse INTO @proc END\nCLOSE curse\nDEALLOCATE curse\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e \u003c/p\u003e","title":"SQL Tricks"},{"content":"Usage\nstring domain = \u0026quot;ExampleDomain\u0026quot;; string userName = \u0026quot;ExampleUserName\u0026quot;; string password = \u0026quot;ExamplePassword\u0026quot;; using (Impersonation impersonation = new Impersonation(domain, userName, password)) { // impersonation occuring in here Console.WriteLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name); } Implementation\n","permalink":"https://blog.mckelt.com/articles/posts/impersonation-in-microsoft-dot-net/","summary":"\u003cp\u003e\u003cem\u003e\u003cstrong\u003eUsage\u003c/strong\u003e\u003c/em\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003estring domain = \u0026quot;ExampleDomain\u0026quot;;\nstring userName = \u0026quot;ExampleUserName\u0026quot;;\nstring password = \u0026quot;ExamplePassword\u0026quot;; \n\nusing (Impersonation impersonation = new Impersonation(domain, userName, password))\n{\n // impersonation occuring in here \n         Console.WriteLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name);\n} \n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003eImplementation\u003c/strong\u003e\u003c/em\u003e\u003c/p\u003e\n\u003cscript src=\"https://gist.github.com/chrismckelt/846be3c45554f20263daf3c6173da2c1.js\"\u003e\u003c/script\u003e","title":"Impersonation in Microsoft Dot Net"},{"content":"Simple export of a datatable to excel without using COM+\nExcel will ask if you want to open this as \u0026lsquo;An XML List\u0026rsquo;\nSaveFileDialog fileDialog = new SaveFileDialog(); fileDialog.Filter = \u0026quot;Excel files (\\*.xls)|\\*.xls\u0026quot;; fileDialog.FileName = \u0026quot;My\\_File\\_Name.xls\u0026quot;; fileDialog.ShowDialog(); DataTable dt = GetFilteredDataTable(); using (FileStream fs = (FileStream)fileDialog.OpenFile()) using (StreamWriter sw = new StreamWriter(fs)) { sw.Write(\u0026quot;\u0026lt;?xml version=\\\\\u0026quot;1.0\\\\\u0026quot; standalone=\\\\\u0026quot;yes\\\\\u0026quot;?\u0026gt;\u0026quot;); dt.WriteXml(sw, XmlWriteMode.IgnoreSchema); sw.Close(); fs.Close(); } ","permalink":"https://blog.mckelt.com/articles/posts/winforms-export-datatable-to-excel-without-com/","summary":"\u003cp\u003eSimple export of a datatable to excel without using COM+\u003c/p\u003e\n\u003cp\u003eExcel will ask if you want to open this as \u0026lsquo;An XML List\u0026rsquo;\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eSaveFileDialog fileDialog = new SaveFileDialog();\nfileDialog.Filter = \u0026quot;Excel files (\\*.xls)|\\*.xls\u0026quot;;\nfileDialog.FileName = \u0026quot;My\\_File\\_Name.xls\u0026quot;;\nfileDialog.ShowDialog();\n\nDataTable dt = GetFilteredDataTable();\n\nusing (FileStream fs = (FileStream)fileDialog.OpenFile())\nusing (StreamWriter sw = new StreamWriter(fs))\n{\n  sw.Write(\u0026quot;\u0026lt;?xml version=\\\\\u0026quot;1.0\\\\\u0026quot; standalone=\\\\\u0026quot;yes\\\\\u0026quot;?\u0026gt;\u0026quot;);\n  dt.WriteXml(sw, XmlWriteMode.IgnoreSchema);\n  sw.Close();\n  fs.Close();\n}   \n\u003c/code\u003e\u003c/pre\u003e","title":"Winforms export datatable to excel without COM+"},{"content":"Convert.ToChar(34).ToString() Converting the corresponding number to an character 33 = !\n34 = \u0026quot;\n35 = #\n36 = $\n37 = %\n38 = \u0026amp;\n39 = \u0026rsquo;\n40 = (\n41 = )\n42 = *\n43 = +\n44 = ,\n45 = -\n46 = .\n47 = /\n48 = 0\n49 = 1\n50 = 2\n51 = 3\n52 = 4\n53 = 5\n54 = 6\n55 = 7\n56 = 8\n57 = 9\n58 = :\n59 = ;\n60 = \u0026lt;\n61 = =\n62 = \u0026gt;\n63 = ?\n64 = @\n65 = A\n66 = B\n67 = C\n68 = D\n69 = E\n70 = F\n71 = G\n72 = H\n73 = I\n74 = J\n75 = K\n76 = L\n77 = M\n78 = N\n79 = O\n80 = P\n81 = Q\n82 = R\n83 = S\n84 = T\n85 = U\n86 = V\n87 = W\n88 = X\n89 = Y\n90 = Z\n91 = [\n92 = \\\n93 = ]\n94 = ^\n95 = _\n96 = `\n97 = a\n98 = b\n99 = c\n100 = d\n101 = e\n102 = f\n103 = g\n104 = h\n105 = i\n106 = j\n107 = k\n108 = l\n109 = m\n110 = n\n111 = o\n112 = p\n113 = q\n114 = r\n115 = s\n116 = t\n117 = u\n118 = v\n119 = w\n120 = x\n121 = y\n122 = z\n123 = {\n124 = |\n125 = }\n126 = ~\n","permalink":"https://blog.mckelt.com/articles/posts/converting-ints-to-char/","summary":"\u003ch1 id=\"converttochar34tostring\"\u003eConvert.ToChar(34).ToString()\u003c/h1\u003e\n\u003cp\u003eConverting the corresponding number to an character \n \u003c/p\u003e\n\u003cp\u003e33 = \u003cstrong\u003e!\u003c/strong\u003e\u003cbr\u003e\n34 = \u003cstrong\u003e\u0026quot;\u003c/strong\u003e\u003cbr\u003e\n35 = \u003cstrong\u003e#\u003c/strong\u003e\u003cbr\u003e\n36 = \u003cstrong\u003e$\u003c/strong\u003e\u003cbr\u003e\n37 = \u003cstrong\u003e%\u003c/strong\u003e\u003cbr\u003e\n38 = \u003cstrong\u003e\u0026amp;\u003c/strong\u003e\u003cbr\u003e\n39 = \u003cstrong\u003e\u0026rsquo;\u003c/strong\u003e\u003cbr\u003e\n40 = \u003cstrong\u003e(\u003c/strong\u003e\u003cbr\u003e\n41 = \u003cstrong\u003e)\u003c/strong\u003e\u003cbr\u003e\n42 = \u003cstrong\u003e*\u003c/strong\u003e\u003cbr\u003e\n43 = \u003cstrong\u003e+\u003c/strong\u003e\u003cbr\u003e\n44 = \u003cstrong\u003e,\u003c/strong\u003e\u003cbr\u003e\n45 = \u003cstrong\u003e-\u003c/strong\u003e\u003cbr\u003e\n46 = \u003cstrong\u003e.\u003c/strong\u003e\u003cbr\u003e\n47 = \u003cstrong\u003e/\u003c/strong\u003e\u003cbr\u003e\n48 = \u003cstrong\u003e0\u003c/strong\u003e\u003cbr\u003e\n49 = \u003cstrong\u003e1\u003c/strong\u003e\u003cbr\u003e\n50 = \u003cstrong\u003e2\u003c/strong\u003e\u003cbr\u003e\n51 = \u003cstrong\u003e3\u003c/strong\u003e\u003cbr\u003e\n52 = \u003cstrong\u003e4\u003c/strong\u003e\u003cbr\u003e\n53 = \u003cstrong\u003e5\u003c/strong\u003e\u003cbr\u003e\n54 = \u003cstrong\u003e6\u003c/strong\u003e\u003cbr\u003e\n55 = \u003cstrong\u003e7\u003c/strong\u003e\u003cbr\u003e\n56 = \u003cstrong\u003e8\u003c/strong\u003e\u003cbr\u003e\n57 = \u003cstrong\u003e9\u003c/strong\u003e\u003cbr\u003e\n58 = \u003cstrong\u003e:\u003c/strong\u003e\u003cbr\u003e\n59 = \u003cstrong\u003e;\u003c/strong\u003e\u003cbr\u003e\n60 = \u003cstrong\u003e\u0026lt;\u003c/strong\u003e\u003cbr\u003e\n61 = \u003cstrong\u003e=\u003c/strong\u003e\u003cbr\u003e\n62 = \u003cstrong\u003e\u0026gt;\u003c/strong\u003e\u003cbr\u003e\n63 = \u003cstrong\u003e?\u003c/strong\u003e\u003cbr\u003e\n64 = \u003cstrong\u003e@\u003c/strong\u003e\u003cbr\u003e\n65 = \u003cstrong\u003eA\u003c/strong\u003e\u003cbr\u003e\n66 = \u003cstrong\u003eB\u003c/strong\u003e\u003cbr\u003e\n67 = \u003cstrong\u003eC\u003c/strong\u003e\u003cbr\u003e\n68 = \u003cstrong\u003eD\u003c/strong\u003e\u003cbr\u003e\n69 = \u003cstrong\u003eE\u003c/strong\u003e\u003cbr\u003e\n70 = \u003cstrong\u003eF\u003c/strong\u003e\u003cbr\u003e\n71 = \u003cstrong\u003eG\u003c/strong\u003e\u003cbr\u003e\n72 = \u003cstrong\u003eH\u003c/strong\u003e\u003cbr\u003e\n73 = \u003cstrong\u003eI\u003c/strong\u003e\u003cbr\u003e\n74 = \u003cstrong\u003eJ\u003c/strong\u003e\u003cbr\u003e\n75 = \u003cstrong\u003eK\u003c/strong\u003e\u003cbr\u003e\n76 = \u003cstrong\u003eL\u003c/strong\u003e\u003cbr\u003e\n77 = \u003cstrong\u003eM\u003c/strong\u003e\u003cbr\u003e\n78 = \u003cstrong\u003eN\u003c/strong\u003e\u003cbr\u003e\n79 = \u003cstrong\u003eO\u003c/strong\u003e\u003cbr\u003e\n80 = \u003cstrong\u003eP\u003c/strong\u003e\u003cbr\u003e\n81 = \u003cstrong\u003eQ\u003c/strong\u003e\u003cbr\u003e\n82 = \u003cstrong\u003eR\u003c/strong\u003e\u003cbr\u003e\n83 = \u003cstrong\u003eS\u003c/strong\u003e\u003cbr\u003e\n84 = \u003cstrong\u003eT\u003c/strong\u003e\u003cbr\u003e\n85 = \u003cstrong\u003eU\u003c/strong\u003e\u003cbr\u003e\n86 = \u003cstrong\u003eV\u003c/strong\u003e\u003cbr\u003e\n87 = \u003cstrong\u003eW\u003c/strong\u003e\u003cbr\u003e\n88 = \u003cstrong\u003eX\u003c/strong\u003e\u003cbr\u003e\n89 = \u003cstrong\u003eY\u003c/strong\u003e\u003cbr\u003e\n90 = \u003cstrong\u003eZ\u003c/strong\u003e\u003cbr\u003e\n91 = \u003cstrong\u003e[\u003c/strong\u003e\u003cbr\u003e\n92 = \u003cstrong\u003e\\\u003c/strong\u003e\u003cbr\u003e\n93 = \u003cstrong\u003e]\u003c/strong\u003e\u003cbr\u003e\n94 = \u003cstrong\u003e^\u003c/strong\u003e\u003cbr\u003e\n95 = \u003cstrong\u003e_\u003c/strong\u003e\u003cbr\u003e\n96 = \u003cstrong\u003e`\u003c/strong\u003e\u003cbr\u003e\n97 = \u003cstrong\u003ea\u003c/strong\u003e\u003cbr\u003e\n98 = \u003cstrong\u003eb\u003c/strong\u003e\u003cbr\u003e\n99 = \u003cstrong\u003ec\u003c/strong\u003e\u003cbr\u003e\n100 = \u003cstrong\u003ed\u003c/strong\u003e\u003cbr\u003e\n101 = \u003cstrong\u003ee\u003c/strong\u003e\u003cbr\u003e\n102 = \u003cstrong\u003ef\u003c/strong\u003e\u003cbr\u003e\n103 = \u003cstrong\u003eg\u003c/strong\u003e\u003cbr\u003e\n104 = \u003cstrong\u003eh\u003c/strong\u003e\u003cbr\u003e\n105 = \u003cstrong\u003ei\u003c/strong\u003e\u003cbr\u003e\n106 = \u003cstrong\u003ej\u003c/strong\u003e\u003cbr\u003e\n107 = \u003cstrong\u003ek\u003c/strong\u003e\u003cbr\u003e\n108 = \u003cstrong\u003el\u003c/strong\u003e\u003cbr\u003e\n109 = \u003cstrong\u003em\u003c/strong\u003e\u003cbr\u003e\n110 = \u003cstrong\u003en\u003c/strong\u003e\u003cbr\u003e\n111 = \u003cstrong\u003eo\u003c/strong\u003e\u003cbr\u003e\n112 = \u003cstrong\u003ep\u003c/strong\u003e\u003cbr\u003e\n113 = \u003cstrong\u003eq\u003c/strong\u003e\u003cbr\u003e\n114 = \u003cstrong\u003er\u003c/strong\u003e\u003cbr\u003e\n115 = \u003cstrong\u003es\u003c/strong\u003e\u003cbr\u003e\n116 = \u003cstrong\u003et\u003c/strong\u003e\u003cbr\u003e\n117 = \u003cstrong\u003eu\u003c/strong\u003e\u003cbr\u003e\n118 = \u003cstrong\u003ev\u003c/strong\u003e\u003cbr\u003e\n119 = \u003cstrong\u003ew\u003c/strong\u003e\u003cbr\u003e\n120 = \u003cstrong\u003ex\u003c/strong\u003e\u003cbr\u003e\n121 = \u003cstrong\u003ey\u003c/strong\u003e\u003cbr\u003e\n122 = \u003cstrong\u003ez\u003c/strong\u003e\u003cbr\u003e\n123 = \u003cstrong\u003e{\u003c/strong\u003e\u003cbr\u003e\n124 = \u003cstrong\u003e|\u003c/strong\u003e\u003cbr\u003e\n125 = \u003cstrong\u003e}\u003c/strong\u003e\u003cbr\u003e\n126 = \u003cstrong\u003e~\u003c/strong\u003e\u003c/p\u003e","title":"Converting ints to char"},{"content":"Hello! Here I attempt to write down random stuff I have learnt.\nFeel free to reach me at chris at mckelt.com\nMy favourite quote So live your life that the fear of death can never enter your heart.\nTrouble no one about their religion;\nrespect others in their view, and demand that they respect yours.\nLove your life, perfect your life, beautify all things in your life.\nSeek to make your life long and its purpose in the service of your people.\nPrepare a noble death song for the day when you go over the great divide.\nAlways give a word or a sign of salute when meeting or passing a friend,\neven a stranger, when in a lonely place.\nShow respect to all people and grovel to none.\nWhen you arise in the morning give thanks for the food and for the joy of living.\nIf you see no reason for giving thanks, the fault lies only in yourself.\nAbuse no one and no thing, for abuse turns the wise ones to fools\nand robs the spirit of its vision.\nWhen it comes your time to die, be not like those whose hearts are filled\nwith the fear of death, so that when their time comes they weep\nand pray for a little more time to live their lives over again in a different way.\nSing your death song and die like a hero going home.\n–Chief Tecumseh (Crouching Tiger) Shawnee Nation 1768-1813\nIt has been said that the greatest souls awaken through suffering. Suffering is not always a curse. Darkness shows us aspects of ourselves that need work, which may not have been exposed to us if the Universe had not sent this suffering in the first place.\nThe greatest prayer you could make would to not ask the Source or God or the Universe to take the suffering away from you, but to instead have faith that everything that happens in your life is only happening to stimulate your spiritual evolution.\nThank the Universe for sending you that suffering to help you grow and evolve, both spiritually and emotionally. All experience is a blessing and happens for a reason, so don\u0026rsquo;t be afraid to feel it and learn from it what it has to show you about yourself.\n","permalink":"https://blog.mckelt.com/articles/posts/hi/","summary":"\u003ch1 id=\"hello\"\u003eHello!\u003c/h1\u003e\n\u003cp\u003eHere I attempt to write down random stuff I have learnt.\u003c/p\u003e\n\u003cp\u003eFeel free to reach me at \u003cstrong\u003echris\u003c/strong\u003e at mckelt.com\u003c/p\u003e\n\u003ch3 id=\"my-favourite-quote\"\u003eMy favourite quote\u003c/h3\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003eSo live your life that the fear of death can never enter your heart.\u003cbr\u003e\nTrouble no one about their religion;\u003cbr\u003e\nrespect others in their view, and demand that they respect yours.\u003cbr\u003e\nLove your life, perfect your life, beautify all things in your life.\u003c/p\u003e\n\u003cp\u003eSeek to make your life long and its purpose in the service of your people.\u003cbr\u003e\nPrepare a noble death song for the day when you go over the great divide.\u003cbr\u003e\nAlways give a word or a sign of salute when meeting or passing a friend,\u003cbr\u003e\neven a stranger, when in a lonely place.\u003cbr\u003e\nShow respect to all people and grovel to none.\u003c/p\u003e","title":"Hi"}]