貝克曼的血球真是讓人很無語,首先廠商傲嬌不給支持,文檔跟天書似的,不能出圖又要被醫院吐槽技術不行什麼的。爲了他的圖也是費盡心思啊(碰到了就自求多福吧,哈哈)。分享一下解析邏輯,碰到這種事的小夥伴少走點彎路。先欣賞一波儀器文檔。
直方圖還能稍稍理解一下
數據圖(這是內部人員自己的筆記吧)
經過各種找資料試啊終於解析出來了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LIS.BLL.ImageCore;
using System.Drawing;
using System.Data;
using System.IO;
using System.Drawing.Drawing2D;
namespace LIS.Mach.ImageDeal
{
///<summary NoteObject="Class">
/// [功能描述:LH780出圖] <para/>
/// [創建者:zlz] <para/>
/// [創建時間:2018年01月31日] <para/>
///<說明>
/// [說明:[功能描述:LH780出圖]<para/>
///</說明>
///<修改記錄>
/// [修改時間:本次修改時間]<para/>
/// [修改內容:本次修改內容]<para/>
///</修改記錄>
///<修改記錄>
/// [修改時間:本次修改時間]<para/>
/// [修改內容:本次修改內容]<para/>
/// M端觸發代碼,其他的和監聽程序一樣,直方圖多條線用#分割數據
/// s retObj=##Class(wbsLisMsgAsyncHandler.LISMsg.wbsLisDrawImageAsyncHandlerSoap).%New()
/// s ret=retObj.DrawImage("1","繪圖數據","儀器","處理M","傳輸次數","其他參數","LIS.Mach.ImageDeal.ImageDealTest,LIS.Mach.ImageDeal")
/// s ret=$$DealImage^MI.MIF000(epis,"RBC繪圖數據串",mi,"和監聽一樣的有保存圖片的M類","-1","Histogram#RBCH.bmp#######10#10#320#138","LIS.Mach.ImageDeal.ImageDealLH780,LIS.Mach.ImageDeal")
/// s ret=$$DealImage^MI.MIF000(epis,"PLT繪圖數據串",mi,"和監聽一樣的有保存圖片的M類","-1","Histogram#PLT.bmp#######10#10#320#138","LIS.Mach.ImageDeal.ImageDealLH780,LIS.Mach.ImageDeal")
/// s ret=$$DealImage^MI.MIF000(epis,"WBC繪圖數據串",mi,"和監聽一樣的有保存圖片的M類","-1","Histogram#WBCF.bmp#######10#10#320#138","LIS.Mach.ImageDeal.ImageDealLH780,LIS.Mach.ImageDeal")
/// s ret=$$DealImage^MI.MIF000(epis,"WBC繪圖數據串",mi,"和監聽一樣的有保存圖片的M類","-1","DiffPlot#DIFF.bmp#######10#10#320#138","LIS.Mach.ImageDeal.ImageDealLH780,LIS.Mach.ImageDeal")
///</修改記錄>
///</summary>
public class ImageDealLH780 : BaseDeal, IDrawImage
{
/// <summary>
/// 繪圖方法
/// </summary>
/// <param name="epis">流水號</param>
/// <param name="result">結果</param>
/// <param name="machID">儀器ID</param>
/// <param name="dealProcess">處理M</param>
/// <param name="index">-1認爲傳到最後</param>
/// <param name="otherPara">其他參數</param>
/// <param name="dealClass">C#處理類格式:類全名,不帶後綴的動態庫名</param>
/// <returns>是否成功</returns>
public bool DrawImage(string epis, string result, string machID, string dealProcess, string index, string otherPara, string dealClass)
{
int cunt = 0;
try
{
//string epis = row["Epis"].ToString();
//1.1從其他參數中獲取所需要的參數
string[] paraList = otherPara.Split('#');
string graphType = "";
string imgClass = "";
string label = "";
string title = "";
string maxDot = "";
string maxValue = "";
string memo = "";
string foreColor = "";
string top = "";
string left = "";
string width = "";
string height = "";
if (paraList.Length > 1)
{
graphType = paraList[0];
imgClass = paraList[1];
}
else
{
return true;
}
if (paraList.Length > 11)
{
title = paraList[2];
label = paraList[3];
maxDot = paraList[4];
maxValue = paraList[5];
memo = paraList[6];
foreColor = paraList[7];
top = paraList[8];
left = paraList[9];
width = paraList[10];
height = paraList[11];
}
//#2.1校驗必要參數是否存在
if (String.IsNullOrEmpty(width))
{
width = "320";
}
if (String.IsNullOrEmpty(height))
{
height = "138";
}
if (String.IsNullOrEmpty(foreColor))
{
foreColor = "0";
}
//#2.2取得畫圖所需要的元素
double imageWidth = Convert.ToDouble(width);
double imageHeight = Convert.ToDouble(height);
//#2.3分不同類型的圖形來進行繪圖
//畫直方圖
if (graphType == "Histogram")
{
string[] resArr = result.Split('#');
Bitmap image = null;
for (int zi = 0; zi < resArr.Length; zi++)
{
result=resArr[zi];
if (result == "")
{
continue;
}
float[] dot = new float[result.Length / 2];
float imgMaxValue = 0;
int indexD = 0;
for (int i = 0; i < result.Length - 2; i = i + 2)
{
dot[indexD] = Convert.ToInt32(result[i] + "", 16) * 16 + Convert.ToInt32(result[i + 1] + "", 16);
if (dot[indexD] > imgMaxValue)
{
imgMaxValue = dot[indexD];
}
indexD++;
}
//沒傳背景畫普通的
if (imgClass == "")
{
Histogram histogram = new Histogram(label, title, dot.Length, imgMaxValue, foreColor, Convert.ToInt32(width), Convert.ToInt32(height));
histogram.Values = dot;
image = histogram.CreateImage();
}
//傳了特殊畫
else
{
image = CreateImage(imgClass, imgMaxValue, dot, image);
}
}
//判斷C盤trak是否存在
string tmpPath = @"c:\TRAK\tmpMach";
if (!Directory.Exists("C:\\TRAK"))
{
Directory.CreateDirectory("C:\\TRAK"); //新建文件夾
if (!Directory.Exists(tmpPath))
{
Directory.CreateDirectory(tmpPath); //新建文件夾
}
}
//先刪除臨時目錄裏面的所有文件
DeleteFolder(tmpPath);
image.Save(tmpPath + "\\" + imgClass.Replace(".bmp","") + epis + ".bmp");
image.Dispose();
string ftpPath = "";
FtpService ftp = GetFtpHelper(machID, dealProcess, out ftpPath);
////上傳圖片
ftp.Upload(tmpPath + "\\" + imgClass.Replace(".bmp", "") + epis + ".bmp");
//保存圖片
SaveImg(machID, epis, imgClass.Replace(".bmp", ""), ftpPath.Split('^')[3] + imgClass.Replace(".bmp", "") + epis + ".bmp", dealProcess);
File.Delete(tmpPath + "\\" + imgClass.Replace(".bmp", "") + epis + ".bmp");
}
else if (graphType == "DiffPlot")
{
string renderingData = "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000020100000100000000000000000000000100000102010000010000000000000201000001010100000102000001000000010200010101000101010000010000020102000101010102010100010101000101010101020101010101000101010001010101010201010101010100010101010101010101010101010101000000000000000000000000000000000000000000000000000300000000000000000000000304000004000000000000000000000003000003040300000300000000000003030000030403000003040000030000000304000304030003030300000300000303040003040303030303000303030003030303030403030303040003030300040303030303030303030304030303030303030303030303030303030000000000000000000000000000000000000000000000000005000000000000000000000004050000050000000000000000000000050000050604000004000000000000040500000506050000050400000500000005040005060500040505000005000004050500050605050505040006050500050605050605060505050500060505000605060505060506060506050606060606060606060606060606060600000000000000000000000000000000000000000000000000070000000000000000000000070800000700000000000000000000000700000708070000070000000000000708000008070800000807000008000000080700080708000807080000080000080807000807080808080700080809000808070808090808080808000808080008080808080808080808080808080808080808080808080808080808000000000000000000000000000000000000000000000000000A0000000000000000000000070A00000A00000000000000000000000A00000A070A00000A000000000000020A00000A070A00000A0200000A0000000A0700070A0A000A0A0A00000A00000A0A0A000A0A0A0A0A0A0A000A000A00000A000A0A000A00000A000A0A000A00000A000A0A000A00000A000A0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B00000000000000000000000000000000000000000000000000030000000000000000000000030B0000020000000000000000000000030000020B0B000002000000000000030B00000203020000020B00000B0000000B030002030200020C0B00000200000B030B00020302020B020B00020B02000B0302020203030B0B020B000B0202000203030B03030B02020B02030B03030B020B02020B02030B030B0B030008";
if (renderingData.Length < 1920)
{
LIS.Core.Util.LogUtils.WriteExceptionLog("繪製散點圖失敗", new Exception("渲染數據數據不能少於60x32"));
return false;
}
if (result.Length < 8160)
{
LIS.Core.Util.LogUtils.WriteExceptionLog("繪製散點圖失敗", new Exception("數據少於8160"));
return false;
}
List<string> renderList = new List<string>();
for (int z = 0; z < 60; z++)
{
renderList.Add(renderingData.Substring(z * 32, 32));
}
int leftInt = 0;
int topInt = 0;
int curX = leftInt;
int curY = topInt;
int imgWidth = 255;
StringBuilder dataplotBlock = new StringBuilder();
Bitmap img = null;
//#1.2獲得畫圖句柄
Graphics g = null;
Image imgtmp = Image.FromStream(GetImageStram(imgClass)) as Bitmap;
img = new Bitmap(imgtmp.Width, imgtmp.Height);
g = Graphics.FromImage(img);
g.Clear(Color.White);
//+抗鋸齒
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawImage(imgtmp, 0, 0, img.Width, img.Height);
Pen pen = new Pen(Color.Black);
for (int i = 0; i < result.Length-1; i += 2)
{
int renderingIndex = Convert.ToInt32(result[i] + "", 16) * 16 + Convert.ToInt32(result[i + 1] + "", 16);
if (renderingIndex >= renderList.Count)
{
continue;
}
for (int heightInt = 0; heightInt < 4; heightInt++)
{
for (int widthInt = 0; widthInt < 4; widthInt++)
{
int begin = (heightInt * 4 + widthInt) * 2;
string colorVal = renderList[renderingIndex].Substring(begin, 2);
string curColor = "";
if (colorVal == "00")
{
curColor = "#000000";
}
else if (colorVal == "01")
{
curColor = "#FFFFFF";
}
else if (colorVal == "02")
{
curColor = "#606060";
}
else if (colorVal == "03")
{
curColor = "#FF0000";
}
else if (colorVal == "04")
{
curColor = "#FFFF00";
}
else if (colorVal == "05")
{
curColor = "#FF00FF";
}
else if (colorVal == "06")
{
curColor = "#800080";
}
else if (colorVal == "07")
{
curColor = "#00FFFF";
}
else if (colorVal == "08")
{
curColor = "#00FF00";
}
else if (colorVal == "09")
{
curColor = "#008000";
}
else if (colorVal == "0A")
{
curColor = "#0000FF";
}
else if (colorVal == "0B")
{
curColor = "#000080";
}
else if (colorVal == "0C")
{
curColor = "#800000";
}
else if (colorVal == "0D")
{
curColor = "#808080";
}
else
{
curColor = "#000000";
}
if (curColor != "#000000")
{
if (curX + widthInt < img.Width && curY + heightInt < img.Height)
{
pen.Color = System.Drawing.ColorTranslator.FromHtml(curColor);
g.DrawEllipse(pen, curX + widthInt, curY + heightInt, 1, 1);
cunt++;
}
}
}
}
curX += 4;
if (curX > imgWidth)
{
curY += 4;
curX = leftInt;
}
}
//判斷C盤trak是否存在
string tmpPath = @"c:\TRAK\tmpMach";
if (!Directory.Exists("C:\\TRAK"))
{
Directory.CreateDirectory("C:\\TRAK"); //新建文件夾
if (!Directory.Exists(tmpPath))
{
Directory.CreateDirectory(tmpPath); //新建文件夾
}
}
//先刪除臨時目錄裏面的所有文件
DeleteFolder(tmpPath);
img.Save(tmpPath + "\\" + imgClass.Replace(".bmp", "") + epis + ".bmp");
img.Dispose();
string ftpPath = "";
FtpService ftp = GetFtpHelper(machID, dealProcess, out ftpPath);
////上傳圖片
ftp.Upload(tmpPath + "\\" + imgClass.Replace(".bmp", "") + epis + ".bmp");
//保存圖片
SaveImg(machID, epis, imgClass.Replace(".bmp", ""), ftpPath.Split('^')[3] + imgClass.Replace(".bmp", "") + epis + ".bmp", dealProcess);
File.Delete(tmpPath + "\\" + imgClass.Replace(".bmp", "") + epis + ".bmp");
}
return true;
}
catch (Exception ex)
{
LIS.Core.Util.LogUtils.WriteExceptionLog("繪製H780圖發生錯誤,數據串:" + result+" 其他參數:"+otherPara , ex);
return false;
}
}
/// 清空指定的文件夾,但不刪除文件夾
/// </summary>
/// <param name="dir"></param>
public static void DeleteFolder(string dir)
{
foreach (string d in Directory.GetFileSystemEntries(dir))
{
if (File.Exists(d))
{
FileInfo fi = new FileInfo(d);
if ((DateTime.Now - fi.CreationTime).Minutes > 10)
{
if (fi.Attributes.ToString().IndexOf("ReadOnly") != -1)
{
fi.Attributes = FileAttributes.Normal;
}
File.Delete(d);//直接刪除其中的文件
}
}
else
{
DirectoryInfo d1 = new DirectoryInfo(d);
if (d1.GetFiles().Length != 0)
{
DeleteFolder(d1.FullName);////遞歸刪除子文件夾
}
Directory.Delete(d);
}
}
}
/// <summary>
/// 獲得圖片流
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public Stream GetImageStram(string name)
{
return this.GetType().Assembly.GetManifestResourceStream("LIS.Mach.ImageDeal.Image." + name);
}
/// <summary>
/// 畫圖邏輯
/// </summary>
public Bitmap CreateImage(string bgName, float MaxValue, float[] Values, Bitmap imageold)
{
//#1.畫座標系,先簡單畫兩條線,暫時不做細節
Bitmap img = null;
//#1.2獲得畫圖句柄
Graphics g = null;
if (imageold != null)
{
img = imageold;
g = Graphics.FromImage(img);
}
else
{
Image imgtmp = Image.FromStream(GetImageStram(bgName)) as Bitmap;
img = new Bitmap(imgtmp.Width, imgtmp.Height);
g = Graphics.FromImage(img);
g.Clear(Color.White);
//+抗鋸齒
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawImage(imgtmp, 0, 0, img.Width, img.Height);
}
int Height = img.Height;
//#1.3偏移
int x = 1;
int y = 20;
//畫橫縱座標線
Pen pen = new Pen(Color.Black);
pen.Width = 2;
//#3.開始進點的數據,進行繪圖
double radix = (img.Width - 30)*1.0 / Values.Length;
if (Values.Length == 256)
{
radix = radix * 2;
}
float preY = -1;
int curindex = 0;
double radiy = 1;
if (MaxValue != 0)
{
radiy = (Height - 40)*1.0 / MaxValue;
}
foreach (var d in Values)
{
if (preY == -1)
{
pen = new Pen(Color.Black);
pen.Width = 1;
}
else
{
pen = new Pen(Color.Black);
pen.Width = 1;
if (10 + x * radix > img.Width)
{
continue;
}
if (Height - d * radiy - y > img.Height || Height - d * radiy - y<0)
{
continue;
}
g.DrawLine(pen, 10 + (int)(x * radix), Height - (int)(d * radiy) - y, 10 + (int)((x - 1) * radix), preY - y);
}
preY = Height - (int)(d * radiy);
x += 1;
curindex++;
}
return img;
}
}
}
直方圖得到Y座標邏輯(實際理解每兩個字符用十六進制表示一個Y座標)
解散點圖邏輯部分(不知道什麼意義,反正最後效果出來了)
效果
RBC數據
0405040302020101020202020101000000000102020202030406070A0E1014181E242B343F4A535E6B7B8B9BA9B5BEC5CCCCCBC6C0BAB3ACA0918274675A5149433B332A231E1A1716141211100F0F0F0F0F0F0F101010100F1010101010111211121111101010100F0F0F0F0E0E0E0D0C0B0A0B0B0B0A0909090807070706060605050505050606060605040302020201010202010101010101000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
PLT數據
000000000003132F42566679859199A4B4C4C8C8C8CCCCC8C8C0B8B0ACA8A4A0A0A09C8D81756D66625E5A56524E463E36332F2F2B2B2B272327232723231F1F0F1B1F1B171B0B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
WBCF數據
000000000000000000000000000000000000663939332C261F191F26333F4C5F7999ACB8BFBFBFC5CCCCBFAC928C7F725F524639332C2C2C2C2C33332C33333333332C2C2C2C2C2C2C2C2C2C2C26261F1F1F1F1F1F1F1F1F19191913131319131313131313130C0C0C130C0C0C060606060C0C0C0C13131313130C0C13191919191919191F1F2626262626262C3339393F393F3F46464646464C5259595F5F666C6C6C666C6C72797F7F7F8C92928C7F8585857F797979797F7F7F726C6C6C7272797979726C665F5F5F5F5F5F5F5F5959595F5F594C463F3F393933332C261F1F1F1F261F191313191913131313131313130C0C06060C0C0606060000000000
散點圖數據
00000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000151615001500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F00000000000000150015151500001515000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F00000000001F15000016150016001500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F1F0000000000000000000015001515150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001516151616000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F000000000000001615150000001515000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F1F001F001F0000150015150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001515161600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F000000001F000000150015150016151515150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F000000000000001600001516000000150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F00001F00000017001516001515000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F00200000201F1F0000000000150016150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F001F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F0000241F210000150016001515150015001515000000000000150000000000000000000000000000000000000000000000000000000000000000000000001F0000001F001F22001F1F00001617171716151815001500000000000000000000000000000000000000000000000000000000000000000000000000000000001F1F1F202120202020211500150015160000171616001500000000000015000000000B0000000000000000000000000000000000000000000000000000000000001F1F001F1F1F2323201F00000000001516181516000015151500001500000000000000000B0000000000000000000000000000000000000000000000000000000000001F2220242223202015001615171619151516151500000000001500000B000B0000000000000000000000000000000000000000000000000000000000001F001F202323242423202000001515181918191A18161715150000000000000B0B0B00000B0000000000000000000000000000000000000000000000000000291F2022202222242520212015151900171A1B1B1A1915160000151500150000000000000000000000000000000000000000000000000000000000000000001F1F201F23232324252421210015151518181B1B1B1B16181617151516160000000B0000000000000000000000000000000000000000000000000000000000001F001F1F210024242424231F1F000019181A1B1B1C1C1B1B1515150015171500000B0B000B0B000000000000000000000000000000000000000000000000001F000020002023212425251F2018170016191A1B1C1C1C1C1B161517151500160000000000000B000000000000000000000000000000000000000000001F00000000001F00201F232422222320001516151A1B1C1C1C1C1C1B1A15161516170015150C0C0C0B000B000000000000000000000000000000000000000000000000001F0000200020242423221F1715151616191C1C1C1C1C1C1C181A16161500160015000B0D0C0B00000000000000000000000000000000000000000000000000001F201F202120212020232015151515191B1B1C1C1C1C1C1C1A1717001517161515000B000C0C000000000000000000000000000000000000000000000000000000001F002320001F202000151515171B1B1C1C1D1D1C1C1B1A1A161816161500150B0C0B0C00000B0000000000000000000000000000000000000000000000000029011F00201F00001F00160018181B1B1C1D1D1D1D1C1C1A00160000000015000C00000000000000000000000000000000000000000000000000000000000000002A2122002000000000151515001A1B1C1D1D1D1C1C1B1A1616001615001500000B0C00000000000000000000000000000000000000000000000000000029290029292020000000000015001718191C1C1D1D1D1C1C1B1716151600000000160B00000D0B000000000000000000000000000000000000000000000000000029292A0000000029011515001516181B1C1C1D1D1C1C1C1B171500000000000000000B0C000000000000000000000000000000000000000000002900000029292B292A29292A0000000017001517151B1B1C1D1D1C1C1B1A18000000150000000000000C0000000000000000000000000000000000000000000000002929292A00012A29012A2900291516150000191A1B1C1C1C1C1B1B170000150000150000000B000B00000000000000000000000000000000000000000000000029292B292A2B01012B2C2900010000001618161A1B1B1C1C1B1B1916000000150000000000000B00000000000000000000000000000000000000000000000000002B002A2D01012D2E2B012B01000016001518181A1B1A1A1B1A161500000000000000000000000B000000000000000000000000000000000029000000002900002A2E2D2F2F2F2E2E2E2A010016000015150017191A1A19171715000000000000000000000B00000000000000000000000000000000000000000000000000002B2B2E2F2F2F2F01012D2E2A292B00000015161516001716001515000000000000000000000C0000000000000000000000000000000000000000000000002A2B2C2C2E2F012F302F2F0101012A0101001600151515151516160000000000000000000000000000000000000000000000000000000000002900000000000029002C2E2E010130302F022F022B01000129151516000015150000000015000000000000000000000000000000000000000000000000000000000000002A292A29292F2F2F303030012F2E2F2E2D2C000000000000001500151515000000000000000000000000000000000000000000000000000000000000000000000029002B002D2F2F30302F302F2F2E2E2C2C2929290000000000290000000000002900000000000000000000000000000000000000000000000000000000000029292B2C2C2D2F2F2F2F2F302F2F2F2F2C292A290029290000000000000000000000290000000000000000000000000000000000000000000000000000000029002B2A2D2D2E2E2E2F2F2F2F2F2F2B2D2B2C2B0000002A00000000000000002900000000000000000000000000000000000000000000000000000000000000000000292A2D2C2E2E2F2D2E2F2F2D2E2C002B000029000000000000000000000000000000000000000000000000000000000000000000000000000000000029002929292B2A2D2F2F2F2F2F2E2F2E2C2A292A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029002C2D2C2D2E2F2E2E2D2E2D2D2B2B0029002900000000000000002900000000000000000000000000000000000000000000000000000000000000000000000000292C2E2E2E2F2E2E2E2E2D2B2C2C290000000000000000001500000000000000000000000000000000000000000000000000000000000000000000002900002B002B2A2A2D2C2C2D2A29292A29292A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002B002900002B2D2D002A2900002900000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000000000000000000000292A0000002B2A002900000029000000000000000000000000000000000000000000000000000000000000000000000000000000000000290000000000000000000000290029000000000000000000000000000015000000000000000000000015000000000000000000000000000000000000000000000000000000290000000000000029000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033003300000000000000003300000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000033003300340000000000333300000000330000000000000034000000000000000000000000000000000000000000000000000000000000000000000000000000333333333300003333333400330033000000343300340000003300000033000000000033000000000000000000000000000000330000000000000000000000003400003300330000343433330034000000330000000000003333000033000000000000000033000000000000000000000000000000000033000000000000000000340000330000003433330033003500003333000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000340000330000003400000000000033000000330000000000000033000000000000000000330000000000000000000000000000000000000000000033000000003300000000000000000000003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000