사용예제
using
무슨 일이 있어도 반드시 종료 처리를 호출하고 싶을 때는 using문과 IDisposable(using System)인터페이스를 사용하면 됌
using문이 끝날 때 객체가 가진 Dispose 메서드를 자동으로 호출해서 파일을 닫기 때문에
Close가 없어도 작동한다.
간단한 Dispose를 구현한 클래스 예제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
2019년 3월 31일 일요일
2019년 3월 26일 화요일
부채꼴 그리기
(UI용 아님)
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
public class CircularSectorMeshRenderer : MonoBehaviour
{
public float degree = 180;
public float intervalDegree = 5;
public float beginOffsetDegree = 0;
public float radius = 10;
Mesh mesh;
MeshFilter meshFilter;
Vector3[] vertices;
int[] triangles;
Vector2[] uvs;
int i;
float beginDegree;
float endDegree;
float beginRadian;
float endRadian;
float uvRadius = 0.5f;
Vector2 uvCenter = new Vector2(0.5f, 0.5f);
float currentIntervalDegree = 0;
float limitDegree;
int count;
int lastCount;
float beginCos;
float beginSin;
float endCos;
float endSin;
int beginNumber;
int endNumber;
int triangleNumber;
// Use this for initialization
void Start ()
{
mesh = new Mesh();
meshFilter = (MeshFilter)GetComponent("MeshFilter");
}
// Update is called once per frame
void Update ()
{
currentIntervalDegree = Mathf.Abs(intervalDegree);
count = (int)( Mathf.Abs(degree) / currentIntervalDegree );
if ( degree % intervalDegree != 0 )
{ ++count; }
if ( degree < 0 )
{ currentIntervalDegree = -currentIntervalDegree; }
if ( lastCount != count )
{
mesh.Clear(); vertices = new Vector3[ count*2 + 1 ];
triangles = new int [ count*3 ];
uvs = new Vector2[ count*2 + 1 ];
vertices[0] = Vector3.zero;
uvs[0] = uvCenter;
lastCount = count;
}
i =0;
beginDegree = beginOffsetDegree;
limitDegree = degree + beginOffsetDegree;
while ( i < count )
{
endDegree = beginDegree + currentIntervalDegree;
if ( degree > 0 )
{
if ( endDegree > limitDegree )
{
endDegree = limitDegree;
}
} else
{
if ( endDegree < limitDegree )
{
endDegree = limitDegree;
}
}
beginRadian = Mathf.Deg2Rad * beginDegree; endRadian = Mathf.Deg2Rad * endDegree ;
beginCos = Mathf.Cos( beginRadian );
beginSin = Mathf.Sin( beginRadian );
endCos = Mathf.Cos( endRadian );
endSin = Mathf.Sin( endRadian );
beginNumber = i*2 + 1;
endNumber = i*2 + 2;
triangleNumber = i*3;
vertices[ beginNumber ].x = beginCos * radius;
vertices[ beginNumber ].y = 0;
vertices[ beginNumber ].z = beginSin * radius;
vertices[ endNumber ].x = endCos * radius;
vertices[ endNumber ].y = 0;
vertices[ endNumber ].z = endSin * radius;
triangles[ triangleNumber ] = 0;
if ( degree > 0 )
{
triangles[ triangleNumber + 1 ] = endNumber;
triangles[ triangleNumber + 2 ] = beginNumber;
} else
{
triangles[ triangleNumber + 1 ] = beginNumber;
triangles[ triangleNumber + 2 ] = endNumber;
}
if ( radius > 0 )
{
uvs[ beginNumber ].x = beginCos * uvRadius + uvCenter.x;
uvs[ beginNumber ].y = beginSin * uvRadius + uvCenter.y;
uvs[ endNumber ].x = endCos * uvRadius + uvCenter.x;
uvs[ endNumber ].y = endSin * uvRadius + uvCenter.y;
} else
{
uvs[ beginNumber ].x = -beginCos * uvRadius + uvCenter.x;
uvs[ beginNumber ].y = -beginSin * uvRadius + uvCenter.y;
uvs[ endNumber ].x = -endCos * uvRadius + uvCenter.x;
uvs[ endNumber ].y = -endSin * uvRadius + uvCenter.y;
}
beginDegree += currentIntervalDegree; ++i;
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
meshFilter.sharedMesh = mesh;
meshFilter.sharedMesh.name = "CircularSectorMesh";
}
}
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
public class CircularSectorMeshRenderer : MonoBehaviour
{
public float degree = 180;
public float intervalDegree = 5;
public float beginOffsetDegree = 0;
public float radius = 10;
Mesh mesh;
MeshFilter meshFilter;
Vector3[] vertices;
int[] triangles;
Vector2[] uvs;
int i;
float beginDegree;
float endDegree;
float beginRadian;
float endRadian;
float uvRadius = 0.5f;
Vector2 uvCenter = new Vector2(0.5f, 0.5f);
float currentIntervalDegree = 0;
float limitDegree;
int count;
int lastCount;
float beginCos;
float beginSin;
float endCos;
float endSin;
int beginNumber;
int endNumber;
int triangleNumber;
// Use this for initialization
void Start ()
{
mesh = new Mesh();
meshFilter = (MeshFilter)GetComponent("MeshFilter");
}
// Update is called once per frame
void Update ()
{
currentIntervalDegree = Mathf.Abs(intervalDegree);
count = (int)( Mathf.Abs(degree) / currentIntervalDegree );
if ( degree % intervalDegree != 0 )
{ ++count; }
if ( degree < 0 )
{ currentIntervalDegree = -currentIntervalDegree; }
if ( lastCount != count )
{
mesh.Clear(); vertices = new Vector3[ count*2 + 1 ];
triangles = new int [ count*3 ];
uvs = new Vector2[ count*2 + 1 ];
vertices[0] = Vector3.zero;
uvs[0] = uvCenter;
lastCount = count;
}
i =0;
beginDegree = beginOffsetDegree;
limitDegree = degree + beginOffsetDegree;
while ( i < count )
{
endDegree = beginDegree + currentIntervalDegree;
if ( degree > 0 )
{
if ( endDegree > limitDegree )
{
endDegree = limitDegree;
}
} else
{
if ( endDegree < limitDegree )
{
endDegree = limitDegree;
}
}
beginRadian = Mathf.Deg2Rad * beginDegree; endRadian = Mathf.Deg2Rad * endDegree ;
beginCos = Mathf.Cos( beginRadian );
beginSin = Mathf.Sin( beginRadian );
endCos = Mathf.Cos( endRadian );
endSin = Mathf.Sin( endRadian );
beginNumber = i*2 + 1;
endNumber = i*2 + 2;
triangleNumber = i*3;
vertices[ beginNumber ].x = beginCos * radius;
vertices[ beginNumber ].y = 0;
vertices[ beginNumber ].z = beginSin * radius;
vertices[ endNumber ].x = endCos * radius;
vertices[ endNumber ].y = 0;
vertices[ endNumber ].z = endSin * radius;
triangles[ triangleNumber ] = 0;
if ( degree > 0 )
{
triangles[ triangleNumber + 1 ] = endNumber;
triangles[ triangleNumber + 2 ] = beginNumber;
} else
{
triangles[ triangleNumber + 1 ] = beginNumber;
triangles[ triangleNumber + 2 ] = endNumber;
}
if ( radius > 0 )
{
uvs[ beginNumber ].x = beginCos * uvRadius + uvCenter.x;
uvs[ beginNumber ].y = beginSin * uvRadius + uvCenter.y;
uvs[ endNumber ].x = endCos * uvRadius + uvCenter.x;
uvs[ endNumber ].y = endSin * uvRadius + uvCenter.y;
} else
{
uvs[ beginNumber ].x = -beginCos * uvRadius + uvCenter.x;
uvs[ beginNumber ].y = -beginSin * uvRadius + uvCenter.y;
uvs[ endNumber ].x = -endCos * uvRadius + uvCenter.x;
uvs[ endNumber ].y = -endSin * uvRadius + uvCenter.y;
}
beginDegree += currentIntervalDegree; ++i;
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
meshFilter.sharedMesh = mesh;
meshFilter.sharedMesh.name = "CircularSectorMesh";
}
}
그냥 그래프(실시간)
public void TestGraphDraw(int val,float yVal)
{
DateTime time = ConvertFromUnixTimestamp(val);
int tmp_time;
int.TryParse(ChartDateUtility.DateToValuexxx(time).ToString(), out tmp_time);
if (MainGraph.DataSource.m_TotalLineCount > 1)
{
double diff_X = double.Parse(tmp_time.ToString()) - tmp_points.Last()._x;
if (diff_X < 0)
{
//날짜가 지낫다면
Debug.Log("날짜가 지났다");
ReDrawGraph("1");
}
}
Debug.Log("count" + MainGraph.DataSource.m_TotalLineCount);
if (tmp_points.Count == 60)
{
tmp_points.RemoveAt(0);
tmp_Pos tmp = new tmp_Pos(double.Parse(tmp_time.ToString()), double.Parse(yVal.ToString()));
tmp_points.Add(tmp);
}else if (tmp_points.Count < 60)
{
tmp_Pos tmp = new tmp_Pos(double.Parse(tmp_time.ToString()), double.Parse(yVal.ToString()));
tmp_points.Add(tmp);
}
AddPointRealtime_forgGraph("1", tmp_time, yVal);
//horiOrigin = MainGraph.DataSource.GetCurrentStartDay("1");
//Debug.Log("horiOrigin" + horiOrigin);
}
//2019-03-26 현재 저장된 Vector3값 tmp_day를 -1 한다음 다시 그리기
public void ReDrawGraph(string categoryName)
{
MainGraph.DataSource.ClearCategory(categoryName);
horiOrigin = null; // 다시 처음부터 그리기 위해서 눈속임용
MainGraph.DataSource.m_TotalLineCount = 0; // 마찬가지로 눈속임용 저장한 그래프를 다시 그린다.
foreach (var val in tmp_points)
{
//Debug.Log("val x:" + val._x);
AddPointRealtime_forgGraph(categoryName, int.Parse((val._x - 86400).ToString()), float.Parse(val._y.ToString()));
}
//Debug.Log("totalLineCOunt:" + MainGraph.DataSource.m_TotalLineCount);
tmp_points.Clear();
}
public void func_RemoveLast(string categoryName,int idx)
{
horiOrigin = null;
MainGraph.DataSource.RemoveAtCategory(categoryName, idx);
MainGraph.DataSource.HorizontalViewOrigin = MainGraph.DataSource.GetCurrentStartDay("1");
--MainGraph.DataSource.m_TotalLineCount;
//horiOrigin = MainGraph.DataSource.GetCurrentStartDay("1"); //horiOrigin 옮기기
}
{
DateTime time = ConvertFromUnixTimestamp(val);
int tmp_time;
int.TryParse(ChartDateUtility.DateToValuexxx(time).ToString(), out tmp_time);
if (MainGraph.DataSource.m_TotalLineCount > 1)
{
double diff_X = double.Parse(tmp_time.ToString()) - tmp_points.Last()._x;
if (diff_X < 0)
{
//날짜가 지낫다면
Debug.Log("날짜가 지났다");
ReDrawGraph("1");
}
}
Debug.Log("count" + MainGraph.DataSource.m_TotalLineCount);
if (tmp_points.Count == 60)
{
tmp_points.RemoveAt(0);
tmp_Pos tmp = new tmp_Pos(double.Parse(tmp_time.ToString()), double.Parse(yVal.ToString()));
tmp_points.Add(tmp);
}else if (tmp_points.Count < 60)
{
tmp_Pos tmp = new tmp_Pos(double.Parse(tmp_time.ToString()), double.Parse(yVal.ToString()));
tmp_points.Add(tmp);
}
AddPointRealtime_forgGraph("1", tmp_time, yVal);
//horiOrigin = MainGraph.DataSource.GetCurrentStartDay("1");
//Debug.Log("horiOrigin" + horiOrigin);
}
//2019-03-26 현재 저장된 Vector3값 tmp_day를 -1 한다음 다시 그리기
public void ReDrawGraph(string categoryName)
{
MainGraph.DataSource.ClearCategory(categoryName);
horiOrigin = null; // 다시 처음부터 그리기 위해서 눈속임용
MainGraph.DataSource.m_TotalLineCount = 0; // 마찬가지로 눈속임용 저장한 그래프를 다시 그린다.
foreach (var val in tmp_points)
{
//Debug.Log("val x:" + val._x);
AddPointRealtime_forgGraph(categoryName, int.Parse((val._x - 86400).ToString()), float.Parse(val._y.ToString()));
}
//Debug.Log("totalLineCOunt:" + MainGraph.DataSource.m_TotalLineCount);
tmp_points.Clear();
}
public void func_RemoveLast(string categoryName,int idx)
{
horiOrigin = null;
MainGraph.DataSource.RemoveAtCategory(categoryName, idx);
MainGraph.DataSource.HorizontalViewOrigin = MainGraph.DataSource.GetCurrentStartDay("1");
--MainGraph.DataSource.m_TotalLineCount;
//horiOrigin = MainGraph.DataSource.GetCurrentStartDay("1"); //horiOrigin 옮기기
}
2019년 3월 25일 월요일
시간변환 문제
23시 : 82800
59분 : 3540
86340 다음에 00000으로 돌아감
맨 앞에 그냥 day 랑 month 더해서 계산하면 해결될듯 하지만 그러면 9자리라 7자리 넘어감 (Max는 7자리)
그냥 받은 datetime을 분으로 변환한다음 day 랑 month 더하면 딱 7자리? ㄴㄴㄴㄴㄴ안됨 분으로 하면 시간비교안됨
방법은 자 일단 초로 해서 5자리는 사용해서 비교 무조껀 해야함 여기서 앞에 두자리 더 쓸수 있다고 생각하고
해결법
날짜가 변경된거를 체크해서 tmp_day (전역변수)에 하루만큼 플러스 1을 해준다
문제점 tmp_day가 3자리수가 넘어가면 똑같은 문제 발생(7자리 넘어감)
문제해결방법 : 모든초가 00000 이 됬을때 그리고 그래프를 다 그렷을때(꽉차게 그렷다) tmp_day를 0으로
x축 첫번째가 1day가 됬다면
모든 그래프의 좌표를 일단 저장 (1데이들의 좌표)
tmp_day를 0으로 변환하고 새로운 좌표 찍기
저장했던 모든 좌표들의 tmp_day도 0으로 변환(-1day해준거로 찍으면됨)
///위에 방식으로 그릴수가 없음 앞에 아무 값이나 넣으면 날짜가 변경되어버림
토탈초에서
86400 으로 나눈값의 몫이 바뀔때 가 날짜가 변할때임
그러면 거기서 하루(86400)을 빼주고 다시 그려주면 끝임
59분 : 3540
86340 다음에 00000으로 돌아감
맨 앞에 그냥 day 랑 month 더해서 계산하면 해결될듯 하지만 그러면 9자리라 7자리 넘어감 (Max는 7자리)
그냥 받은 datetime을 분으로 변환한다음 day 랑 month 더하면 딱 7자리? ㄴㄴㄴㄴㄴ안됨 분으로 하면 시간비교안됨
방법은 자 일단 초로 해서 5자리는 사용해서 비교 무조껀 해야함 여기서 앞에 두자리 더 쓸수 있다고 생각하고
해결법
날짜가 변경된거를 체크해서 tmp_day (전역변수)에 하루만큼 플러스 1을 해준다
문제점 tmp_day가 3자리수가 넘어가면 똑같은 문제 발생(7자리 넘어감)
문제해결방법 : 모든초가 00000 이 됬을때 그리고 그래프를 다 그렷을때(꽉차게 그렷다) tmp_day를 0으로
x축 첫번째가 1day가 됬다면
모든 그래프의 좌표를 일단 저장 (1데이들의 좌표)
tmp_day를 0으로 변환하고 새로운 좌표 찍기
저장했던 모든 좌표들의 tmp_day도 0으로 변환(-1day해준거로 찍으면됨)
///위에 방식으로 그릴수가 없음 앞에 아무 값이나 넣으면 날짜가 변경되어버림
토탈초에서
86400 으로 나눈값의 몫이 바뀔때 가 날짜가 변할때임
그러면 거기서 하루(86400)을 빼주고 다시 그려주면 끝임
2019년 3월 22일 금요일
forgGraph 만드는데 문제점 발생..ㅠㅠ
직접 시간 넣어서 그래프 그려보기
;;;; 시간이 시간이 중복되서 들어감
원인
Vector3는 float만 지원을함
time값을 second로 변환해서 쓰는데 double이 필요할정도로 큰값을 씀
결론
double이 지원되는 Vector3를 사용해보자 (잇긴함 깃허브에)
문제점: 그래프 그리는 함수안에 Vector3 (float)을 사용하는곳이 너무 많아 수정 너무 많음
해결중...
맨처음에 시간을 변환한것을 string으로 받아온다 거기서 시작함
해당 string을 이쁜 float (부동소수가 빠진)으로 변환 할 수 있으면 그래프 그릴수있음
문제...string을 float로 변환하니까 부동소수를 쳐 붙인 버전을 보여줌...그래서 아마 안될꺼같음...
substring으로 잘라서 쓴다..
7자리까지 밖에 지원안됨..더 길면 쓸수없는방법..
방법 3.
Minute만 계산하면 계산은 됨(단위가 확 줄으니까..) 하지만 대소비교가 안될듯하고
전부 계산하고 년도만 빼면 될꺼같기도한데...
년도는 그래프의 맨위에 따로 표시면 될것같기도 한데...
해결함
해결방법
public static int DateToValuexxx(DateTime dateTime)
{
int result;
double tmp1;
double tmp2;
tmp1 = (dateTime.Date - Epoch.Date).TotalSeconds;
tmp2 = (dateTime - Epoch).TotalSeconds;
int.TryParse((tmp2 - tmp1).ToString(), out result);
return result;
}
애초에 전부다 계산한 TotalSeconds를 사용하려고 했던게 애바임
date를 빼고 그냥 날짜랑 시간으로만 해서 해결
문제점 2019-03-22
꿈틀거림(변경될때마다) (해결)
;;;; 시간이 시간이 중복되서 들어감
원인
Vector3는 float만 지원을함
time값을 second로 변환해서 쓰는데 double이 필요할정도로 큰값을 씀
결론
double이 지원되는 Vector3를 사용해보자 (잇긴함 깃허브에)
문제점: 그래프 그리는 함수안에 Vector3 (float)을 사용하는곳이 너무 많아 수정 너무 많음
해결중...
맨처음에 시간을 변환한것을 string으로 받아온다 거기서 시작함
해당 string을 이쁜 float (부동소수가 빠진)으로 변환 할 수 있으면 그래프 그릴수있음
문제...string을 float로 변환하니까 부동소수를 쳐 붙인 버전을 보여줌...그래서 아마 안될꺼같음...
substring으로 잘라서 쓴다..
7자리까지 밖에 지원안됨..더 길면 쓸수없는방법..
방법 3.
Minute만 계산하면 계산은 됨(단위가 확 줄으니까..) 하지만 대소비교가 안될듯하고
전부 계산하고 년도만 빼면 될꺼같기도한데...
년도는 그래프의 맨위에 따로 표시면 될것같기도 한데...
해결함
해결방법
public static int DateToValuexxx(DateTime dateTime)
{
int result;
double tmp1;
double tmp2;
tmp1 = (dateTime.Date - Epoch.Date).TotalSeconds;
tmp2 = (dateTime - Epoch).TotalSeconds;
int.TryParse((tmp2 - tmp1).ToString(), out result);
return result;
}
애초에 전부다 계산한 TotalSeconds를 사용하려고 했던게 애바임
date를 빼고 그냥 날짜랑 시간으로만 해서 해결
문제점 2019-03-22
꿈틀거림(변경될때마다) (해결)
2019년 3월 21일 목요일
360 각도 조절기 cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
[RequireComponent(typeof(RectTransform))]
public class RadialSlider : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerDownHandler
{
public SprinklerController sprinklerController; // 스프링클러 컨트롤러
public RectTransform centerPivot; // 회전시킬 피벗 (원점)
public float slideArea = 10f; // 슬라이드 할 수 있는 영역의 거리 (원의 외곽선으로부터의 거리)
[Range(0f, 360f)] public float minAngle = 0f; // 슬라이드 영역 최소 각도
[Range(0f, 360f)] public float maxAngle = 360f; // 슬라이드 영역 최대 각도
private float outerRadius; // 원의 외부 반지름
private float innerRadius; // 원의 내부 반지름 (내부 반지름은 0보다 크고 외부 반지름보다 작아야 함!)
private bool isSlideArea = false; // 슬라이드 영역 내부를 클릭했는지 여부
// Use this for initialization
void Start()
{
outerRadius = ((RectTransform)transform).rect.width / 2f; // 외부 반지름 설정
innerRadius = outerRadius - slideArea; // 내부 반지름 설정
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// 포인트의 각도를 변환하는 메서드
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
private float GetAngle(Vector2 point)
{
float angle = Mathf.Atan2(point.x, point.y) * Mathf.Rad2Deg;
angle = (angle + 360f) % 360f; // 양수만 나오게 360도를 더한 후 360도로 모듈러 연산 수행
return angle;
}
public void OnBeginDrag(PointerEventData eventData)
{
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
// 드래그를 시작한 포인트가 원의 외부 반지름보다 큰 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y > outerRadius * outerRadius)
return;
// 드래그를 시작한 포인트가 원의 내부 반지름보다 작은 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y < innerRadius * innerRadius)
return;
float angle = GetAngle(point);
if (angle < minAngle || angle > maxAngle)
return;
isSlideArea = true;
}
public void OnDrag(PointerEventData eventData)
{
if (!isSlideArea)
return;
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
if (centerPivot)
{
float angle = GetAngle(point);
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (!isSlideArea)
return;
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
if (centerPivot)
{
float angle = GetAngle(point); // 라디안 각도를 도로 변환
// UI의 Z축 회전은 World와 반대이기 때문에 -를 해줌
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
isSlideArea = false;
}
public void OnPointerDown(PointerEventData eventData)
{
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
// 마우스 다운 한 포인트가 원의 외부 반지름보다 큰 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y > outerRadius * outerRadius)
return;
// 마우스 다운 한 포인트가 원의 내부 반지름보다 작은 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y < innerRadius * innerRadius)
return;
if (centerPivot)
{
float angle = GetAngle(point); // 라디안 각도를 도로 변환
// UI의 Z축 회전은 World와 반대이기 때문에 -를 해줌
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
}
public void OnPointerClick(PointerEventData eventData)
{
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
[RequireComponent(typeof(RectTransform))]
public class RadialSlider : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerDownHandler
{
public SprinklerController sprinklerController; // 스프링클러 컨트롤러
public RectTransform centerPivot; // 회전시킬 피벗 (원점)
public float slideArea = 10f; // 슬라이드 할 수 있는 영역의 거리 (원의 외곽선으로부터의 거리)
[Range(0f, 360f)] public float minAngle = 0f; // 슬라이드 영역 최소 각도
[Range(0f, 360f)] public float maxAngle = 360f; // 슬라이드 영역 최대 각도
private float outerRadius; // 원의 외부 반지름
private float innerRadius; // 원의 내부 반지름 (내부 반지름은 0보다 크고 외부 반지름보다 작아야 함!)
private bool isSlideArea = false; // 슬라이드 영역 내부를 클릭했는지 여부
// Use this for initialization
void Start()
{
outerRadius = ((RectTransform)transform).rect.width / 2f; // 외부 반지름 설정
innerRadius = outerRadius - slideArea; // 내부 반지름 설정
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// 포인트의 각도를 변환하는 메서드
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
private float GetAngle(Vector2 point)
{
float angle = Mathf.Atan2(point.x, point.y) * Mathf.Rad2Deg;
angle = (angle + 360f) % 360f; // 양수만 나오게 360도를 더한 후 360도로 모듈러 연산 수행
return angle;
}
public void OnBeginDrag(PointerEventData eventData)
{
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
// 드래그를 시작한 포인트가 원의 외부 반지름보다 큰 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y > outerRadius * outerRadius)
return;
// 드래그를 시작한 포인트가 원의 내부 반지름보다 작은 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y < innerRadius * innerRadius)
return;
float angle = GetAngle(point);
if (angle < minAngle || angle > maxAngle)
return;
isSlideArea = true;
}
public void OnDrag(PointerEventData eventData)
{
if (!isSlideArea)
return;
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
if (centerPivot)
{
float angle = GetAngle(point);
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (!isSlideArea)
return;
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
if (centerPivot)
{
float angle = GetAngle(point); // 라디안 각도를 도로 변환
// UI의 Z축 회전은 World와 반대이기 때문에 -를 해줌
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
isSlideArea = false;
}
public void OnPointerDown(PointerEventData eventData)
{
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
// 마우스 다운 한 포인트가 원의 외부 반지름보다 큰 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y > outerRadius * outerRadius)
return;
// 마우스 다운 한 포인트가 원의 내부 반지름보다 작은 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y < innerRadius * innerRadius)
return;
if (centerPivot)
{
float angle = GetAngle(point); // 라디안 각도를 도로 변환
// UI의 Z축 회전은 World와 반대이기 때문에 -를 해줌
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
}
public void OnPointerClick(PointerEventData eventData)
{
}
}
unity 색상 편하게 쓰기 (feat. color 1 to 255)
color는 0~1사이 값을 인자로 받는다
Color ConvertColor(int r, int g, int b)
{
return new Color(r / 255.0f, g / 255.0f, b / 255.0f);
}
이 함수를 쓰면 캔버스에 나오는색과 동일한 값을 넣어 사용하면 된다
ex
return CovertColor(255,164,0);
Color ConvertColor(int r, int g, int b)
{
return new Color(r / 255.0f, g / 255.0f, b / 255.0f);
}
이 함수를 쓰면 캔버스에 나오는색과 동일한 값을 넣어 사용하면 된다
ex
return CovertColor(255,164,0);
2019년 3월 16일 토요일
파일처리
텍스트파일을 IEnumeralbe<string>으로 취급한다.
var filePath = @"C:/Example/Greeting.txt";
var lines = File.ReadLines(filePath, Encoding.UTF8);
foreach (var line in lines)
Debug.Log("line" + line);
ReadLines를 이용하며니 LINQ를 조합해서 다채로운 처리를 깨끗하게 할 수 있다.
1.첫 n행을 읽는다.
var lines = File.ReadLines(filePath, Encoding.UTF8)
.Take(10)
.ToArray();
첫 10행만 읽어 들입니다.
ReadAllLines 메서드와는 달리 파일의 마지막까지 읽어 들이지는 않습니다(중요).
2. 조건에 일치하는 행의 개수를 센다.
var count = File.ReadLines(filePath, Encoding.UTF8)
.Count(s => s.Contains("Windows"));
Windows라는 문자열이 포함돼 있는 행의 개수를 셉니다.
3.조건에 일치하는 행만 읽어 들인다.
var lines = File.ReadLines(filePath, Encoding.UTF8)
.Where(s => !string.IsNullOrWhiteSpace(s))
.ToArray();
위의 코드는 빈 문자열이나 공백인 행 이외의 행을 읽을 수 있습니다.
IsNullOrWhiteSpace 메서드는 .NET 프레임워크 4 이후에 이용할 수 있는 메서드입니다.
4.조건에 일치하는 행이 존재하는지 여부를 조사한다.
var exists = File.ReadLines(filePath, Encoding.UTF8)
.Where(s => !string.IsNullOrWhiteSpace(s))
.Any(s => s.All(c => char.IsDigit(c)));
숫자로만 구성된 행이 존재하는지 조사합니다. 빈 행이 존재하면 조건에 일치한다고 판단되지 않도록 미리 where 메서드를 기술하지 않으면 빈 행에 대해서도 s.ALL이 호출되어 true를 만환하므로 미리 where로 거름
5.중복된 행을 제외하고 나열한다.
var lines = File.ReadLines(filePath, Encoding.UTF8)
.Distinct()
.OrderBy(s => s.Length)
.ToArray();
중복된 행을 제외하고 행의 길이가 짧은 순서로 정렬한 후에 배열에 저장합니다.
6.행마다 어떤 변환 처리를 실행한다.
읽어 들인 행에 어떤 변환 처리를 수행하는 예제.
택스트 파일에서 읽어 들인 각 행에 행 번호를 붙이는 코드.
var lines = File.ReadLines(filePath)
.Select((s, ix) => string.Format("{0,4}: {1}", ix + 1, s))
.ToArray();
foreach (var line in lines)
Debug.Log(line);
7.기존 텍스트 파일의 첫머리에 행을 삽입하는 기능
var filePath = @"C:/Example/Greeting.txt";
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
string texts = reader.ReadToEnd();
stream.Position = 0;
writer.WriteLine("삽입할 새 행1");
writer.WriteLine("삽입할 새 행1");
writer.Write(texts);
}
}
var filePath = @"C:/Example/Greeting.txt";
var lines = File.ReadLines(filePath, Encoding.UTF8);
foreach (var line in lines)
Debug.Log("line" + line);
ReadLines를 이용하며니 LINQ를 조합해서 다채로운 처리를 깨끗하게 할 수 있다.
1.첫 n행을 읽는다.
var lines = File.ReadLines(filePath, Encoding.UTF8)
.Take(10)
.ToArray();
첫 10행만 읽어 들입니다.
ReadAllLines 메서드와는 달리 파일의 마지막까지 읽어 들이지는 않습니다(중요).
2. 조건에 일치하는 행의 개수를 센다.
var count = File.ReadLines(filePath, Encoding.UTF8)
.Count(s => s.Contains("Windows"));
Windows라는 문자열이 포함돼 있는 행의 개수를 셉니다.
3.조건에 일치하는 행만 읽어 들인다.
var lines = File.ReadLines(filePath, Encoding.UTF8)
.Where(s => !string.IsNullOrWhiteSpace(s))
.ToArray();
위의 코드는 빈 문자열이나 공백인 행 이외의 행을 읽을 수 있습니다.
IsNullOrWhiteSpace 메서드는 .NET 프레임워크 4 이후에 이용할 수 있는 메서드입니다.
4.조건에 일치하는 행이 존재하는지 여부를 조사한다.
var exists = File.ReadLines(filePath, Encoding.UTF8)
.Where(s => !string.IsNullOrWhiteSpace(s))
.Any(s => s.All(c => char.IsDigit(c)));
숫자로만 구성된 행이 존재하는지 조사합니다. 빈 행이 존재하면 조건에 일치한다고 판단되지 않도록 미리 where 메서드를 기술하지 않으면 빈 행에 대해서도 s.ALL이 호출되어 true를 만환하므로 미리 where로 거름
5.중복된 행을 제외하고 나열한다.
var lines = File.ReadLines(filePath, Encoding.UTF8)
.Distinct()
.OrderBy(s => s.Length)
.ToArray();
중복된 행을 제외하고 행의 길이가 짧은 순서로 정렬한 후에 배열에 저장합니다.
6.행마다 어떤 변환 처리를 실행한다.
읽어 들인 행에 어떤 변환 처리를 수행하는 예제.
택스트 파일에서 읽어 들인 각 행에 행 번호를 붙이는 코드.
var lines = File.ReadLines(filePath)
.Select((s, ix) => string.Format("{0,4}: {1}", ix + 1, s))
.ToArray();
foreach (var line in lines)
Debug.Log(line);
7.기존 텍스트 파일의 첫머리에 행을 삽입하는 기능
var filePath = @"C:/Example/Greeting.txt";
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
string texts = reader.ReadToEnd();
stream.Position = 0;
writer.WriteLine("삽입할 새 행1");
writer.WriteLine("삽입할 새 행1");
writer.Write(texts);
}
}
2019년 3월 15일 금요일
딕셔너리 응용
1.딕셔너리로 변환한다.
LINQ에 있는 ToDictionary 메서드를 사용하면 배열이나 리스트를 딕셔너리로 변환할 수 있습니다.
딕셔너리로 변환하면 키를 지정해서 해당 값에 빠르게 접근할 수 있습니다.
다음 코드는 List<Employee>를 Dictionary<int, Employee>로 변환하는 예입니다.
var employees = new List<Employee>();
var employeeDict = employees.ToDictionary(emp => emp.Code);
이 코드에서 ToDictionary 메서드의 첫 번째 인수에 사원 코드(emp.Code)를 나타내는 람다식을 넘겨줍니다. 이렇게 함ㄴ 사원코드를 'KEY'로 이용하고 Employee 객체를 '값'으로 이용해서 딕셔너리를 생성할 수 있습니다.
2. 딕셔너리로 부터 다른 딕셔너리를 생성
var flowerDict = new Dictionary<string, int>() {
["sunflower"] = 400,
["pansy"] = 300,
["tulip"] = 200,
["rose"] = 500,
["dahila"] = 400,
};
var newDict = flowerDict.Where(x => x.Value >= 400)
.ToDictionary(flower => flower.Key, flower => flower.Value);
foreach (var item in newDict.Keys)
{
Debug.Log("value:" + item);
}
LINQ에 있는 ToDictionary 메서드를 사용하면 배열이나 리스트를 딕셔너리로 변환할 수 있습니다.
딕셔너리로 변환하면 키를 지정해서 해당 값에 빠르게 접근할 수 있습니다.
다음 코드는 List<Employee>를 Dictionary<int, Employee>로 변환하는 예입니다.
var employees = new List<Employee>();
var employeeDict = employees.ToDictionary(emp => emp.Code);
이 코드에서 ToDictionary 메서드의 첫 번째 인수에 사원 코드(emp.Code)를 나타내는 람다식을 넘겨줍니다. 이렇게 함ㄴ 사원코드를 'KEY'로 이용하고 Employee 객체를 '값'으로 이용해서 딕셔너리를 생성할 수 있습니다.
2. 딕셔너리로 부터 다른 딕셔너리를 생성
var flowerDict = new Dictionary<string, int>() {
["sunflower"] = 400,
["pansy"] = 300,
["tulip"] = 200,
["rose"] = 500,
["dahila"] = 400,
};
var newDict = flowerDict.Where(x => x.Value >= 400)
.ToDictionary(flower => flower.Key, flower => flower.Value);
foreach (var item in newDict.Keys)
{
Debug.Log("value:" + item);
}
2019년 3월 9일 토요일
람다식,LINQ 연습문제
1.람다식을 사용해 다음과 같은 코드를 작성합시다.
var numbers = new List<int> { 12, 87, 94, 14, 53, 20, 40, 35, 76, 91, 31, 17, 48 };
2.List<T>의 ForEach 메서드를 사용해 각 요소를 2.0으로 나눈 값을 콘솔에 출력합니다.
//numbers.ForEach(s => Debug.Log("value :"+ s/2f));
3.LINQ의 Where 매서드를 사용해 값이 50이상인 요소를 열거하고 그 결과를 콘솔에 출력합니다.
//var query = numbers.Where(s => s > 50);
//foreach (int val in query)
// Debug.Log("vale:" + val);
4.LINQ의 Select 매서드를 사용해 각 값을 2배로 만들고 그 결과를 List<int>에 저장합니다.
그리고 List<int>의 각 요소를 콘솔에 출력합니다.
var query2 = numbers.Select(s => s * 2);
List<int> tmp = new List<int>(query2);
foreach (int val in tmp)
Debug.Log("value: " + val);
다음과 같은 리스트가 정의돼 있습니다.
var names = new List<string>
{
"Seoul","New Delhi","Bangkok","London","Paris", "Berlin","Canberra","Hong Kong",
};
1.콘솔의 입력을 받아 도시 이름이 몇번째에 저장돼 있는지 List<T>의 FindIndex를 이용해 return 하는 함수를 짜라 없으면 -1
public int GetIndex(string Cityname)
{
var names = new List<string>
{
"Seoul","New Delhi","Bangkok","London","Paris", "Berlin","Canberra","Hong Kong",
};
int result =-1;
result = names.FindIndex(s => s == Cityname);
return result;
}
2.LINQ의 Count 메서드를 사용해 소문자'o'가 포함된 도시 이름이 몇 개 있는지 세고 그 결과를 콘솔에 출력합니다
.
var Query = names.Count(s => s.Contains("o"));
Debug.Log("Value" + Query);
3.LINQ의 Where 메서드를 사용해 소문자'o'가 포함된 도시 이름을 추출해서 배열에 저장합니다. 그리고 배열의 각 요소를 콘솔에 출력합니다.
var query2 = names.Where(s => s.Contains("o")).ToArray();
foreach (string val in query2)
Debug.Log("value :" + val);
4.LINQ의 Where 메서드와 Select 메서드를 사용해"B"로 시작하는 도시 이름의 문자 개수를 추출하고 그 문자 개수를 콘솔에 출력합니다. 도시 이름은 표시하지 않아도 됩니다.
var query3 = names.Where(s => s.StartsWith("B")).Select(s => s.Length);
foreach (var val in query3)
Debug.Log("value :" + val);
var numbers = new List<int> { 12, 87, 94, 14, 53, 20, 40, 35, 76, 91, 31, 17, 48 };
2.List<T>의 ForEach 메서드를 사용해 각 요소를 2.0으로 나눈 값을 콘솔에 출력합니다.
//numbers.ForEach(s => Debug.Log("value :"+ s/2f));
3.LINQ의 Where 매서드를 사용해 값이 50이상인 요소를 열거하고 그 결과를 콘솔에 출력합니다.
//var query = numbers.Where(s => s > 50);
//foreach (int val in query)
// Debug.Log("vale:" + val);
4.LINQ의 Select 매서드를 사용해 각 값을 2배로 만들고 그 결과를 List<int>에 저장합니다.
그리고 List<int>의 각 요소를 콘솔에 출력합니다.
var query2 = numbers.Select(s => s * 2);
List<int> tmp = new List<int>(query2);
foreach (int val in tmp)
Debug.Log("value: " + val);
다음과 같은 리스트가 정의돼 있습니다.
var names = new List<string>
{
"Seoul","New Delhi","Bangkok","London","Paris", "Berlin","Canberra","Hong Kong",
};
1.콘솔의 입력을 받아 도시 이름이 몇번째에 저장돼 있는지 List<T>의 FindIndex를 이용해 return 하는 함수를 짜라 없으면 -1
public int GetIndex(string Cityname)
{
var names = new List<string>
{
"Seoul","New Delhi","Bangkok","London","Paris", "Berlin","Canberra","Hong Kong",
};
int result =-1;
result = names.FindIndex(s => s == Cityname);
return result;
}
2.LINQ의 Count 메서드를 사용해 소문자'o'가 포함된 도시 이름이 몇 개 있는지 세고 그 결과를 콘솔에 출력합니다
.
var Query = names.Count(s => s.Contains("o"));
Debug.Log("Value" + Query);
3.LINQ의 Where 메서드를 사용해 소문자'o'가 포함된 도시 이름을 추출해서 배열에 저장합니다. 그리고 배열의 각 요소를 콘솔에 출력합니다.
var query2 = names.Where(s => s.Contains("o")).ToArray();
foreach (string val in query2)
Debug.Log("value :" + val);
4.LINQ의 Where 메서드와 Select 메서드를 사용해"B"로 시작하는 도시 이름의 문자 개수를 추출하고 그 문자 개수를 콘솔에 출력합니다. 도시 이름은 표시하지 않아도 됩니다.
var query3 = names.Where(s => s.StartsWith("B")).Select(s => s.Length);
foreach (var val in query3)
Debug.Log("value :" + val);
List 클래스와 람다식의 조합
public class Test : MonoBehaviour
{
//매출 데이터를 읽어 들이고 Sales 객체 리스트를 반환한다.
List<string> list = new List<string> { "seoul", "London", "Bangkok" };
private void Start()
{
//Exist메서드
var exists = list.Exists(s => s[0] == 'a');
//false반환
//Find 메서드
var name = list.Find(s => s.Length == 6);
//FindIndex 메서드
var index = list.FindIndex(s => s == "Berlin");
//FindAll 메서드
var _FindAlllist = list.FindAll(s => s.Length<5);
//seoul만 반환됨 5보다 작으니까
var _removeAllcount = list.RemoveAll(s => s.Length < 5);
//foreach 매서드는
//인수로 지정한 처리 내용을 리스트의 각 요소를 대상으로 실행합니다.
list.ForEach(s => Debug.Log("s" + s));
//convertAll 메서드
//역시 list반환
var ConverAllList = list.ConvertAll(s => s.ToLower());
ConverAllList.ForEach(s => Debug.Log("value: " + s));
}
}
코드가 이뻐질듯!
{
//매출 데이터를 읽어 들이고 Sales 객체 리스트를 반환한다.
List<string> list = new List<string> { "seoul", "London", "Bangkok" };
private void Start()
{
//Exist메서드
var exists = list.Exists(s => s[0] == 'a');
//false반환
//Find 메서드
var name = list.Find(s => s.Length == 6);
//FindIndex 메서드
var index = list.FindIndex(s => s == "Berlin");
//FindAll 메서드
var _FindAlllist = list.FindAll(s => s.Length<5);
//seoul만 반환됨 5보다 작으니까
var _removeAllcount = list.RemoveAll(s => s.Length < 5);
//foreach 매서드는
//인수로 지정한 처리 내용을 리스트의 각 요소를 대상으로 실행합니다.
list.ForEach(s => Debug.Log("s" + s));
//convertAll 메서드
//역시 list반환
var ConverAllList = list.ConvertAll(s => s.ToLower());
ConverAllList.ForEach(s => Debug.Log("value: " + s));
}
}
코드가 이뻐질듯!
2019년 3월 8일 금요일
메서드 없이 속성만 포함한 클래스 정의(feat CSV 파일 로드)
//매출 클래스
public class sale
{
//점포이름
public string ShopName{ get; set; }
//상품 종류
public string ProductCategory{ get; set; }
//매출 액
public int Amount{ get; set; }
};
//ReadSales 메서드
public class Test : MonoBehaviour
{
//매출 데이터를 읽어 들이고 Sales 객체 리스트를 반환한다.
static List<Sale> ReadSales(string filePath)
{
List<Sale> sales = new List<Sale>(); // 매출 데이터를 넣을 리스트 객체를 생성한다
string[] lines = File.ReadAllLines(filePath); // 파일을 한번에 읽어 들인다
foreach (string line in lines) //읽어 들인 행 개수만큼 반복한다
{
string[] items = line.Split(',');
Sale sale = new Sale //세일객체를 생성
{
ShopName = items[0],
ProductCategory = items[1],
Amount = int.Parse(items[2])
};
sales.Add(sale); //Sale객체를 리스트에 추가한다.
}
return sales;
}
}
//점포별 매출 계산
public class SalesCounter
{
private List<Sale> _sales;
//생성자
public SalesCounter(List<Sale> sales)
{
_sales = sales;
}
//dictionary에 집계를 저장한다
public Dictionary<string, int> GetPerStoreSales()
{
Dictionary<string, int> dict = new Dictionary<string, int>();
foreach (Sale sale in _sales)
{
if (dict.ContainsKey(sale.ShopName))
{
dict[sale.ShopName] += sale.Amount;
}
else
dict[sale.ShopName] = sale.Amount;
}
return dict;
}
}
//main
private void Start()
{
SalesCounter sales = new SalesCounter(ReadSales("sales.csv"));
Dictionary<string, int> amountPerStore = sales.GetPerStoreSales();
foreach(KeyValuePair<string,int> obj in amountPerStore)
{
Debug.Log(" key:" +obj.Key + "value:" + obj.Value);
}
}
public class sale
{
//점포이름
public string ShopName{ get; set; }
//상품 종류
public string ProductCategory{ get; set; }
//매출 액
public int Amount{ get; set; }
};
//ReadSales 메서드
public class Test : MonoBehaviour
{
//매출 데이터를 읽어 들이고 Sales 객체 리스트를 반환한다.
static List<Sale> ReadSales(string filePath)
{
List<Sale> sales = new List<Sale>(); // 매출 데이터를 넣을 리스트 객체를 생성한다
string[] lines = File.ReadAllLines(filePath); // 파일을 한번에 읽어 들인다
foreach (string line in lines) //읽어 들인 행 개수만큼 반복한다
{
string[] items = line.Split(',');
Sale sale = new Sale //세일객체를 생성
{
ShopName = items[0],
ProductCategory = items[1],
Amount = int.Parse(items[2])
};
sales.Add(sale); //Sale객체를 리스트에 추가한다.
}
return sales;
}
}
//점포별 매출 계산
public class SalesCounter
{
private List<Sale> _sales;
//생성자
public SalesCounter(List<Sale> sales)
{
_sales = sales;
}
//dictionary에 집계를 저장한다
public Dictionary<string, int> GetPerStoreSales()
{
Dictionary<string, int> dict = new Dictionary<string, int>();
foreach (Sale sale in _sales)
{
if (dict.ContainsKey(sale.ShopName))
{
dict[sale.ShopName] += sale.Amount;
}
else
dict[sale.ShopName] = sale.Amount;
}
return dict;
}
}
//main
private void Start()
{
SalesCounter sales = new SalesCounter(ReadSales("sales.csv"));
Dictionary<string, int> amountPerStore = sales.GetPerStoreSales();
foreach(KeyValuePair<string,int> obj in amountPerStore)
{
Debug.Log(" key:" +obj.Key + "value:" + obj.Value);
}
}
피드 구독하기:
글 (Atom)
git rejected error(feat. cherry-pick)
문제 아무 생각 없이 pull을 받지않고 로컬에서 작업! 커밋, 푸시 진행을 해버렷다. push에선 remote와 다르니 당연히 pull을 진행해라고 하지만 로컬에서 작업한 내용을 백업하지 않고 진행하기에는 부담스럽다(로컬작업 유실 가능성) 해결하려...
-
/// < summary > /// 검색 조건과 내용으로 테이블에 있는 데이터를 검색하는 메서드 /// </ summary > /// < param name = "valu...
-
public class Test : MonoBehaviour { //매출 데이터를 읽어 들이고 Sales 객체 리스트를 반환한다. List<string> list = new List<string> { ...
-
설명과 package파일 https://gitlab.com/dooo3/scrollview_objpool 하는이유 100개 이상일때 scrollview가 퍼포먼스가 떨어진다... Point!!!! 1.shopItemTableViewCell,...