값 출력 비교를 위한 엑셀의 샘플 자료값입니다.

    class Program
    {
        static void Main(string[] args)
        {
            var x = new decimal[] { 20, 30, 40, 50, 60, 70 };
            var y = new decimal[] { 12.48M, 32.33M, 33.11M, 84.12M, 45.91M, 40.11M };

            var cp = CovarianceP(x, y);
            Console.WriteLine("Covariance Population : {0}", cp); //모집단 공분산


            var cs = CovarianceS(x, y);
            Console.WriteLine("Covariance Sample : {0}", cs); //표본집단 공분산

            Console.ReadLine();
        }

        /// <summary>
        /// 모집단 공분산 구하기
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        static decimal CovarianceP(decimal[] x, decimal[] y)
        {
            if (x.Length != y.Length)
                throw new ArgumentException("two parameters must be same length.");

            var avg_x = x.Average();
            var avg_y = y.Average();

            return x.Zip(y, (x1, y1) => (x1 - avg_x) * (y1 - avg_y)).Average();
        }

        /// <summary>
        /// 표본집단 공분산 구하기
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        static decimal CovarianceS(decimal[] x, decimal[] y)
        {
            if (x.Length != y.Length)
                throw new ArgumentException("two parameters must be same length.");

            var avg_x = x.Average();
            var avg_y = y.Average();

            return x.Zip(y, (x1, y1) => (x1 - avg_x) * (y1 - avg_y)).Sum() / (x.Length -1);
        }
    }

 

결과입니다.

double로 하실경우 소수점 마지막자리에 오차가 좀 발생합니다.

 

 

공분산에 대한 설명은 이분 블로그에서 너무나 친절하고 쉽게 설명이 되어 있습니다.

https://blog.naver.com/ikek21/220003173213

 

공분산(covariance)

공분산이 뭐에요? 란 질문에.. 난 당황했었다.. 다.. 당황하셨어요? 그리곤 재빨리 자리를 피했다.. 하지만...

blog.naver.com

 

'C#' 카테고리의 다른 글

asp.net core 3.1, NLog 설정시 문제해결  (0) 2020.06.26
log4net.config 예제  (0) 2019.08.03
GDI+ Bitmap Rotaion  (0) 2019.02.19
WPF RichText에서 HTML 표시하기  (2) 2019.02.09
Visual Studio Debug.WriteLine 표시가 안될때 대처 방안  (2) 2018.11.15

배포환경은 리눅스 Centos7 였습니다.

윈도우 로컬 개발환경에서는 잘 기록되는 NLog가 리눅스 서버에 배포하면 잘 기록되지 않는 문제였습니다.

 

진입점소스는 아래와 같은 형태였었습니다. (네, 인터넷에서 검색해서 그냥 넣었습니다 ㅡㅡ)

        public static void Main(string[] args)
        {
            var config = new ConfigurationBuilder()
                            .SetBasePath(System.IO.Directory.GetCurrentDirectory())
                            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                            .Build();

            NLog.LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));

            var host = CreateHostBuilder(args)
                .Build();
            
            host.Run();
        }

 

그리고 배포시에 사용하는  appsettings.Production.json 파일에 다음과 같이 설정하였습니다.

 

  {"NLog": {
    "variables": {
      "var_logdir": "/var/www/www.mydomain.com/log"
    },
    "targets": {
      "logfile": {
        "type": "File",
        "fileName": "${var_logdir}/nlog-${shortdate}.log"
      },
      "logconsole": {
        "type": "Console"
      }
    }
  }
 }

기본 개발환경에서는 var_logsdir 부분의 값은 "D:\Logs" 였구요..

 

첨에 왜 안되는지 이유를 모르고 좀 헤맸는데, 소스를 보면 간단히 확인되는 문제였습니다.!

 

위에 .AddJsonFile에서 기본적인 appsetting.json 만 해주었기 때문입니다.

(알아서 Production 등이 처리되는 줄... 착각했었네요..)

 

.AddJsonFile ... 부분 하단 라인에 아래와 같이 추가적으로 실행 환경에 맞는 설정을 추가해줘야합니다.

진입 함수에서 아래코드로 확인 가능합니다.

 

var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

 

=== 생략 ===

.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)

.AddEnvironmentVariables()

 

 

 

보통 Startup에서 저런 구성을 넣어주더군요...

 

하지만 굳이 env 불러오지 않고, 아래처럼 소스를 수정하여 해결을 보았습니다.

 

    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args)
                .Build();
            host.Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) => 
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration(ConfigConfiguration) //ConfigConfiguration 호출
                .UseNLog() //NLog 사용
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder
                    .ConfigureKestrel(serverOptions => {
                        serverOptions.Limits.MaxConcurrentConnections = 1000;
                        serverOptions.Limits.MaxConcurrentUpgradedConnections = 1000;
                        serverOptions.Limits.MaxRequestBodySize = 1024 * 1024 * 100;
                        serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100,
                                gracePeriod: TimeSpan.FromSeconds(10));
                        serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100,
                                gracePeriod: TimeSpan.FromSeconds(10));                        
                        serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
                        serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
                    })
                    .UseStartup<Startup>();
                });
        

        static void ConfigConfiguration(HostBuilderContext ctx, IConfigurationBuilder config)
        {            
            NLog.LogManager.Configuration = new NLogLoggingConfiguration(config.Build().GetSection("NLog"));      
        }
    }

 

Builder 구성부분에서 config를 받아 메소드를 수행할 수 있도록 했고.

해당 메소드에서 NLog설정을 셋팅하도록 했습니다.

 

이제 각 환경 Development, Staging, Production 따라 각기 다른 환경에 맞게 로그가 잘 기록이 되는군요.

D:\Logs\2019\20190803\LOG_A_20190803.txt 형식으로 작성이 된다.

 

<?xml version="1.0" encoding="utf-8" ?>

<log4net>

  <appender name="DebugAppender" type="log4net.Appender.DebugAppender" >

    <layout type="log4net.Layout.PatternLayout">

      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />

    </layout>

  </appender>

  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">   

    <file type="log4net.Util.PatternString" value="D:\Logs\%date{yyyy}\%date{yyyy}%date{MM}%date{dd}\LOG_" />

    <datePattern value="'A_'yyyyMMdd'.txt'" />

    <param name="AppendToFile" value="true" />

    <param name="rollingStyle" value="Date" />

    <staticLogFileName value="false" />

    <layout  type="log4net.Layout.PatternLayout">

      <param name="conversionPattern" value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />

    </layout>

  </appender>

  <root>

    <level value="ALL"/>

    <appender-ref ref="DebugAppender" />

    <appender-ref ref="RollingLogFileAppender" />

  </root>

</log4net>

    private Bitmap RotateBitmap(Bitmap bitmap, float angle)
    {
        int w, h, x, y;
        var dW = (double)bitmap.Width;
        var dH = (double)bitmap.Height;

        double degrees = Math.Abs(angle);
        if (degrees <= 90)
        {
            double radians = 0.0174532925 * degrees;
            double dSin = Math.Sin(radians);
            double dCos = Math.Cos(radians);
            w = (int)(dH * dSin + dW * dCos);
            h = (int)(dW * dSin + dH * dCos);
            x = (w - bitmap.Width) / 2;
            y = (h - bitmap.Height) / 2;
        }
        else
        {
            degrees -= 90;
            double radians = 0.0174532925 * degrees;
            double dSin = Math.Sin(radians);
            double dCos = Math.Cos(radians);
            w = (int)(dW * dSin + dH * dCos);
            h = (int)(dH * dSin + dW * dCos);
            x = (w - bitmap.Width) / 2;
            y = (h - bitmap.Height) / 2;
        }

        var rotateAtX = bitmap.Width / 2f;
        var rotateAtY = bitmap.Height / 2f;

        var bmpRet = new Bitmap(w, h);
        bmpRet.SetResolution(bitmap.HorizontalResolution, bitmap.VerticalResolution);
        using (var graphics = Graphics.FromImage(bmpRet))
        {
            graphics.Clear(Color.White);
            graphics.TranslateTransform(rotateAtX + x, rotateAtY + y);
            graphics.RotateTransform(angle);
            graphics.TranslateTransform(-rotateAtX - x, -rotateAtY - y);
            graphics.DrawImage(bitmap, new PointF(0 + x, 0 + y));
        }
        return bmpRet;
    }

https://stackoverflow.com/questions/5172906/rotating-graphics


 RichText에서 HTML을 표시할 수 있는 방법에 대해 설명해놓은 글입니다.

물론 샘플 소스도 같이 있습니다.

https://www.codeproject.com/Articles/1097390/Displaying-HTML-in-a-WPF-RichTextBox


소스를 다운로드해서 샘플을 켜보면 RichText에 TextBox의 Text로 바로 바인딩을 걸어놔서, HTML 문법오류가나면, 바로 프로그램이 죽습니다.

그래서 생성자에 바로 HTML을 입력하고 테스트해보았습니다.






핵심은  HtmlConverter에서 HTML 분석기를 만들어 HtmlToXamlConveter를 호출한다는 겁니다.

FlowDocument 를 만들어서 입력하게끔하네요. 


RTF문서 만들고, 입력내용에 대해 수정하기가 쉽지않은데...

HTML로 하니 간편한 듯합니다..

유용하네요.



MainWindow.xaml


<Window x:Class="RichTextBlockSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:RichTextBlockSample"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="HTML TextBlock sample"
        Width="400"
        Height="300"
        mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBox Name="TextBox"
                 Margin="10,0"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Center"
                 Text=""
                 TextWrapping="Wrap" />
        <RichTextBox Grid.Row="1"
                     local:HtmlRichTextBoxBehavior.Text="{Binding ElementName=TextBox, Path=Text}"
                     IsDocumentEnabled="True"
                     IsReadOnly="True" />
        <!--
        <WebBrowser Grid.Row="2"
                    local:WebBrowserBehavior.Body="{Binding ElementName=TextBox, Path=Text}" />-->
    </Grid>
</Window>



MainWindows.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace RichTextBlockSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
	{
		public MainWindow()
		{
			InitializeComponent();

            TextBox.Text = "<span style=\"color:red; font-size:20px; font-weight:bold\">hello</span>";
            TextBox.Text += "<span style=\"color:blue; font-size:20px; font-weight:bold; font-family:aria\">world</span>";
            TextBox.Text += "<span style=\"color:green; font-size:20px; font-weight:bold; font-family:nanumgothic\">안녕하세요</span>";
        }
	}
}


라이센스 : https://www.codeproject.com/info/cpol10.aspx 보니 소스 재배포가 가능해서 파일 첨부합니다.


RichTextBlockSample.zip



'C#' 카테고리의 다른 글

log4net.config 예제  (0) 2019.08.03
GDI+ Bitmap Rotaion  (0) 2019.02.19
Visual Studio Debug.WriteLine 표시가 안될때 대처 방안  (2) 2018.11.15
WPF, Template Select 하기  (0) 2018.05.29
WPF MVVM 샘플코드  (0) 2018.05.28

1. 빌드하는 모드가 Debug모드인지 확인할 것.


2. 도구 / 옵션 / 디버깅 / 일반에 출력 창의 모든 텍스트를 [직접실행]창으로 리다이렉션 체크해제 확인

(Menu > tools > options > debugging > General > Redirect all output window text to the immediate window (NOT Checked)






2. 프로젝트 설정 페이지에서 빌드, 설정은 빌드, DEBUG 상수 정의, TRACE 상수 정의 확인 

(Project Properties > Build > Define DEBUG constant / Defile TRACE constatnt are all checked.




3. 출력 창에서 마우스 오른쪽 버튼 눌러 프로그램 출력 체크 확인 (이걸 몰라서 헤멨다 아오..)




4. 기타 App.config 에 이런거 있어도 안되고.

  <system.diagnostics>

    <trace>

      <listeners>

        <!-- This next line is the troublemaker. If it is there delete it-->

        <clear/>

      </listeners>

    </trace>

  </system.diagnostics>





'C#' 카테고리의 다른 글

GDI+ Bitmap Rotaion  (0) 2019.02.19
WPF RichText에서 HTML 표시하기  (2) 2019.02.09
WPF, Template Select 하기  (0) 2018.05.29
WPF MVVM 샘플코드  (0) 2018.05.28
doxygen 설치 및 설정  (0) 2018.05.14




C# WPF, 지난번 포스트 소스에 연결됩니다.

상황에 따라, 표시되는 템플릿이 자동으로 지정되게끔 만들 수 있네요.


SubjectSelectDataTemplate.cs

using System.Windows;

using System.Windows.Controls;

 

namespace WPF_MVVM_SAMPLE01

{

    public class SubjectSelectDataTemplate : DataTemplateSelector

    {

        public override DataTemplate SelectTemplate(object item, DependencyObject container)

        {

            Score score = item as Score;

            FrameworkElement el = container as FrameworkElement;

            return (DataTemplate)el.FindResource(score.SCORE > 60 ? "DataTemplate3" : "DataTemplate4");

        }

    }

}



TemplateSelectWindow.xaml

 

<Window x:Class="WpfApp1.TemplateSelectWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"       

        xmlns:local="clr-namespace:WPF_MVVM_SAMPLE01"

        mc:Ignorable="d"

        Title="TemplateSelectWindow" Height="450" Width="800">

    <Window.DataContext>

        <local:ItemViewModel></local:ItemViewModel>

    </Window.DataContext>

    <Window.Resources>

        <local:SubjectSelectDataTemplate x:Key="SubjectSelectDataTemplate"></local:SubjectSelectDataTemplate>

    </Window.Resources>

    <DockPanel>

        <ListBox ItemsSource="{Binding Items}" ItemTemplateSelector="{StaticResource SubjectSelectDataTemplate}" ></ListBox>

    </DockPanel>

</Window>



Dictionary1.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

                    xmlns:local="clr-namespace:WPF_MVVM_SAMPLE01">

    <DataTemplate x:Key="DataTemplate1">

        <TextBlock Text="{Binding SUBJECT}"></TextBlock>

    </DataTemplate>

    <DataTemplate x:Key="DataTemplate2">

        <Grid >

            <Rectangle HorizontalAlignment="Left" Height="30" Width="{Binding SCORE}" StrokeThickness="1" Fill="Red"></Rectangle>

            <TextBlock Text="{Binding SCORE}"></TextBlock>

        </Grid>

    </DataTemplate>

    <DataTemplate x:Key="DataTemplate3">

        <Grid>

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="150"></ColumnDefinition>

                <ColumnDefinition Width="150"></ColumnDefinition>

            </Grid.ColumnDefinitions>

            <TextBlock Grid.Column="0" Text="{Binding SUBJECT}"></TextBlock>

            <Rectangle Grid.Column="1" HorizontalAlignment="Left" Height="30" Width="{Binding SCORE}" StrokeThickness="1" Fill="Red"></Rectangle>

            <TextBlock Grid.Column="1" Text="{Binding SCORE}"></TextBlock>   

        </Grid>

    </DataTemplate>

    <DataTemplate x:Key="DataTemplate4">

        <Grid>

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="150"></ColumnDefinition>

                <ColumnDefinition Width="150"></ColumnDefinition>

            </Grid.ColumnDefinitions>

            <TextBlock Grid.Column="1" Text="{Binding SUBJECT}"></TextBlock>

            <Rectangle Grid.Column="0" HorizontalAlignment="Left" Height="30" Width="{Binding SCORE}" StrokeThickness="1" Fill="Red"></Rectangle>

            <TextBlock Grid.Column="0" Text="{Binding SCORE}"></TextBlock>

        </Grid>

    </DataTemplate>

 

</ResourceDictionary>



소스는 여기 올려뒀습니다. https://github.com/erith/WPF_SAMPLES/tree/master/WpfApp1

WPF에서 MVVM으로 데이터의 출력형태 템플릿을 미리 확인할 수 있습니다,



직장 동료분에게 잠깐 블렌드 사용법을 배웠는데, 기능이 막강합니다. WPF 프로그램 디자인시에는 필수 프로그램이네요. DataContext 설정시, 디자인 타임에, 설정된 템플릿의 형태를 미리 확인할 수 있어 참 편리합니다.



BLEND 실행화면


주요 소스입니다.


MainWindow.xaml

<Window x:Class="WPF_MVVM_SAMPLE01.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:WPF_MVVM_SAMPLE01"

        mc:Ignorable="d"       

        Title="MainWindow" Height="250" Width="350"       

        >

    <Window.DataContext>

        <local:ItemViewModel></local:ItemViewModel>

    </Window.DataContext>

   

    <DockPanel>

        <ListView Width="350" ItemsSource="{Binding Items}" ItemTemplate="{DynamicResource DataTemplate1}" DockPanel.Dock="Top">

            <ListView.View>

                <GridView>

                    <GridViewColumn Header="SUBJECT" Width="150" CellTemplate="{StaticResource DataTemplate1}" ></GridViewColumn>

                    <GridViewColumn Header="SCORE" Width="180"  CellTemplate="{StaticResource DataTemplate2}"></GridViewColumn>

                </GridView>

            </ListView.View>

        </ListView>

    </DockPanel>

</Window>


Dicionary1.xaml


<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

                    xmlns:local="clr-namespace:WPF_MVVM_SAMPLE01">

    <DataTemplate x:Key="DataTemplate1">

        <TextBlock Text="{Binding SUBJECT}"></TextBlock>

    </DataTemplate>

    <DataTemplate x:Key="DataTemplate2">

        <Grid >

            <Rectangle Height="30" Width="{Binding SCORE}" StrokeThickness="1" Fill="Red"></Rectangle>

            <TextBlock Text="{Binding SCORE}"></TextBlock>

        </Grid>

    </DataTemplate>

 

</ResourceDictionary>



ItemViewModel.cs


public class ItemViewModel

    {

        private readonly ScoreCollection items;

 

        public ItemViewModel()

        {

            this.items = new ScoreCollection();

        }

 

        public ScoreCollection Items

        {

            get { return this.items; }

        }

    }


ScoreCollection.cs

using System.Collections.ObjectModel;

 

namespace WPF_MVVM_SAMPLE01

{

    public class ScoreCollection : ObservableCollection<Score>

    {

        public ScoreCollection()

        {

            Add(new Score() { SUBJECT = "Englsh", SCORE = 95 });

            Add(new Score() { SUBJECT = "Mathmatics", SCORE = 55 });

            Add(new Score() { SUBJECT = "History", SCORE = 65 });

        }

    }

 

    public class Score

    {

        public string SUBJECT { get; set; }

        public int SCORE { get; set; }

    }

}



소스: https://github.com/erith/WPF_SAMPLES/tree/master/WpfApp1



+ Recent posts