aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Grid/Manager/OpenGridServices.Manager
diff options
context:
space:
mode:
authorJeff Ames2008-01-10 06:49:29 +0000
committerJeff Ames2008-01-10 06:49:29 +0000
commit5a6fd21a2c31a41c617f1d2a7e390956b5aafb0a (patch)
tree8828dc80f2b50aca4b6726cfe20be5fe5431b12c /OpenSim/Grid/Manager/OpenGridServices.Manager
parent* After fighting with it a bit more, Opensim is now compatible with the most ... (diff)
downloadopensim-SC-5a6fd21a2c31a41c617f1d2a7e390956b5aafb0a.zip
opensim-SC-5a6fd21a2c31a41c617f1d2a7e390956b5aafb0a.tar.gz
opensim-SC-5a6fd21a2c31a41c617f1d2a7e390956b5aafb0a.tar.bz2
opensim-SC-5a6fd21a2c31a41c617f1d2a7e390956b5aafb0a.tar.xz
Whitespace cleanup.
Diffstat (limited to 'OpenSim/Grid/Manager/OpenGridServices.Manager')
-rw-r--r--OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs17
-rw-r--r--OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs45
-rw-r--r--OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs162
-rw-r--r--OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs167
-rw-r--r--OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs134
-rw-r--r--OpenSim/Grid/Manager/OpenGridServices.Manager/RegionBlock.cs52
6 files changed, 284 insertions, 293 deletions
diff --git a/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs b/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs
index b06f731..c8bc8c0 100644
--- a/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs
+++ b/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs
@@ -31,14 +31,11 @@ using System;
31 31
32namespace OpenGridServices.Manager 32namespace OpenGridServices.Manager
33{ 33{
34 34 public partial class Connect to grid server : Gtk.Dialog
35 35 {
36 public partial class Connect to grid server : Gtk.Dialog 36 public Connect to grid server()
37 { 37 {
38 38 this.Build();
39 public Connect to grid server() 39 }
40 { 40 }
41 this.Build();
42 }
43 }
44} 41}
diff --git a/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs b/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs
index bb357a3..1bdb41e 100644
--- a/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs
+++ b/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs
@@ -29,29 +29,26 @@
29using Gtk; 29using Gtk;
30using System; 30using System;
31 31
32namespace OpenGridServices.Manager { 32namespace OpenGridServices.Manager
33 public partial class ConnectToGridServerDialog : Gtk.Dialog 33{
34 { 34 public partial class ConnectToGridServerDialog : Gtk.Dialog
35 35 {
36 public ConnectToGridServerDialog() 36 public ConnectToGridServerDialog()
37 { 37 {
38 this.Build(); 38 this.Build();
39 } 39 }
40
41 protected virtual void OnResponse(object o, Gtk.ResponseArgs args)
42 {
43 switch(args.ResponseId) {
44 case Gtk.ResponseType.Ok:
45 MainClass.PendingOperations.Enqueue("connect_to_gridserver " + this.entry1.Text + " " + this.entry2.Text + " " + this.entry3.Text);
46 break;
47
48 case Gtk.ResponseType.Cancel:
49 break;
50 }
51 this.Hide();
52
53 }
54
55 }
56 40
41 protected virtual void OnResponse(object o, Gtk.ResponseArgs args)
42 {
43 switch(args.ResponseId) {
44 case Gtk.ResponseType.Ok:
45 MainClass.PendingOperations.Enqueue("connect_to_gridserver " + this.entry1.Text + " " + this.entry2.Text + " " + this.entry3.Text);
46 break;
47
48 case Gtk.ResponseType.Cancel:
49 break;
50 }
51 this.Hide();
52 }
53 }
57} 54}
diff --git a/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs b/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs
index 2521e99..255c5e3 100644
--- a/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs
+++ b/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs
@@ -37,98 +37,98 @@ using libsecondlife;
37 37
38namespace OpenGridServices.Manager 38namespace OpenGridServices.Manager
39{ 39{
40 public class GridServerConnectionManager 40 public class GridServerConnectionManager
41 { 41 {
42 private string ServerURL; 42 private string ServerURL;
43 public LLUUID SessionID; 43 public LLUUID SessionID;
44 public bool connected=false; 44 public bool connected=false;
45 45
46 public RegionBlock[][] WorldMap; 46 public RegionBlock[][] WorldMap;
47 47
48 public bool Connect(string GridServerURL, string username, string password) 48 public bool Connect(string GridServerURL, string username, string password)
49 { 49 {
50 try { 50 try {
51 this.ServerURL=GridServerURL; 51 this.ServerURL=GridServerURL;
52 Hashtable LoginParamsHT = new Hashtable(); 52 Hashtable LoginParamsHT = new Hashtable();
53 LoginParamsHT["username"]=username; 53 LoginParamsHT["username"]=username;
54 LoginParamsHT["password"]=password; 54 LoginParamsHT["password"]=password;
55 ArrayList LoginParams = new ArrayList(); 55 ArrayList LoginParams = new ArrayList();
56 LoginParams.Add(LoginParamsHT); 56 LoginParams.Add(LoginParamsHT);
57 XmlRpcRequest GridLoginReq = new XmlRpcRequest("manager_login",LoginParams); 57 XmlRpcRequest GridLoginReq = new XmlRpcRequest("manager_login",LoginParams);
58 XmlRpcResponse GridResp = GridLoginReq.Send(ServerURL,3000); 58 XmlRpcResponse GridResp = GridLoginReq.Send(ServerURL,3000);
59 if(GridResp.IsFault) { 59 if(GridResp.IsFault) {
60 connected=false; 60 connected=false;
61 return false; 61 return false;
62 } else { 62 } else {
63 Hashtable gridrespData = (Hashtable)GridResp.Value; 63 Hashtable gridrespData = (Hashtable)GridResp.Value;
64 this.SessionID = new LLUUID((string)gridrespData["session_id"]); 64 this.SessionID = new LLUUID((string)gridrespData["session_id"]);
65 connected=true; 65 connected=true;
66 return true; 66 return true;
67 } 67 }
68 } catch(Exception e) { 68 } catch(Exception e) {
69 Console.WriteLine(e.ToString()); 69 Console.WriteLine(e.ToString());
70 connected=false; 70 connected=false;
71 return false; 71 return false;
72 } 72 }
73 } 73 }
74 74
75 public void DownloadMap() 75 public void DownloadMap()
76 { 76 {
77 System.Net.WebClient mapdownloader = new WebClient(); 77 System.Net.WebClient mapdownloader = new WebClient();
78 Stream regionliststream = mapdownloader.OpenRead(ServerURL + "/regionlist"); 78 Stream regionliststream = mapdownloader.OpenRead(ServerURL + "/regionlist");
79 79
80 RegionBlock TempRegionData; 80 RegionBlock TempRegionData;
81 81
82 XmlDocument doc = new XmlDocument(); 82 XmlDocument doc = new XmlDocument();
83 doc.Load(regionliststream); 83 doc.Load(regionliststream);
84 regionliststream.Close(); 84 regionliststream.Close();
85 XmlNode rootnode = doc.FirstChild; 85 XmlNode rootnode = doc.FirstChild;
86 if (rootnode.Name != "regions") 86 if (rootnode.Name != "regions")
87 { 87 {
88 // TODO - ERROR! 88 // TODO - ERROR!
89 } 89 }
90 90
91 for(int i=0; i<=rootnode.ChildNodes.Count; i++) 91 for(int i=0; i<=rootnode.ChildNodes.Count; i++)
92 { 92 {
93 if(rootnode.ChildNodes.Item(i).Name != "region") { 93 if(rootnode.ChildNodes.Item(i).Name != "region") {
94 // TODO - ERROR! 94 // TODO - ERROR!
95 } else { 95 } else {
96 TempRegionData = new RegionBlock(); 96 TempRegionData = new RegionBlock();
97 97
98 98
99 } 99 }
100 } 100 }
101 } 101 }
102 102
103 public bool RestartServer() 103 public bool RestartServer()
104 { 104 {
105 return true; 105 return true;
106 } 106 }
107 107
108 public bool ShutdownServer() 108 public bool ShutdownServer()
109 { 109 {
110 try { 110 try {
111 Hashtable ShutdownParamsHT = new Hashtable(); 111 Hashtable ShutdownParamsHT = new Hashtable();
112 ArrayList ShutdownParams = new ArrayList(); 112 ArrayList ShutdownParams = new ArrayList();
113 ShutdownParamsHT["session_id"]=this.SessionID.ToString(); 113 ShutdownParamsHT["session_id"]=this.SessionID.ToString();
114 ShutdownParams.Add(ShutdownParamsHT); 114 ShutdownParams.Add(ShutdownParamsHT);
115 XmlRpcRequest GridShutdownReq = new XmlRpcRequest("shutdown",ShutdownParams); 115 XmlRpcRequest GridShutdownReq = new XmlRpcRequest("shutdown",ShutdownParams);
116 XmlRpcResponse GridResp = GridShutdownReq.Send(this.ServerURL,3000); 116 XmlRpcResponse GridResp = GridShutdownReq.Send(this.ServerURL,3000);
117 if(GridResp.IsFault) { 117 if(GridResp.IsFault) {
118 return false; 118 return false;
119 } else { 119 } else {
120 connected=false; 120 connected=false;
121 return true; 121 return true;
122 } 122 }
123 } catch(Exception e) { 123 } catch(Exception e) {
124 Console.WriteLine(e.ToString()); 124 Console.WriteLine(e.ToString());
125 return false; 125 return false;
126 } 126 }
127 } 127 }
128 128
129 public void DisconnectServer() 129 public void DisconnectServer()
130 { 130 {
131 this.connected=false; 131 this.connected=false;
132 } 132 }
133 } 133 }
134} 134}
diff --git a/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs b/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs
index 78b9761..a2334e1 100644
--- a/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs
+++ b/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs
@@ -26,99 +26,98 @@
26* 26*
27*/ 27*/
28 28
29// project created on 5/14/2007 at 2:04 PM
30using System; 29using System;
31using System.Threading; 30using System.Threading;
32using Gtk; 31using Gtk;
33 32
34namespace OpenGridServices.Manager 33namespace OpenGridServices.Manager
35{ 34{
36 class MainClass 35 class MainClass
37 { 36 {
38 37
39 public static bool QuitReq=false; 38 public static bool QuitReq=false;
40 public static BlockingQueue<string> PendingOperations = new BlockingQueue<string>(); 39 public static BlockingQueue<string> PendingOperations = new BlockingQueue<string>();
41 40
42 private static Thread OperationsRunner; 41 private static Thread OperationsRunner;
43 42
44 private static GridServerConnectionManager gridserverConn; 43 private static GridServerConnectionManager gridserverConn;
45 44
46 private static MainWindow win; 45 private static MainWindow win;
47 46
48 public static void DoMainLoop() 47 public static void DoMainLoop()
49 { 48 {
50 while(!QuitReq) 49 while(!QuitReq)
51 { 50 {
52 Application.RunIteration(); 51 Application.RunIteration();
53 } 52 }
54 } 53 }
55 54
56 public static void RunOperations() 55 public static void RunOperations()
57 { 56 {
58 string operation; 57 string operation;
59 string cmd; 58 string cmd;
60 char[] sep = new char[1]; 59 char[] sep = new char[1];
61 sep[0]=' '; 60 sep[0]=' ';
62 while(!QuitReq) 61 while(!QuitReq)
63 { 62 {
64 operation=PendingOperations.Dequeue(); 63 operation=PendingOperations.Dequeue();
65 Console.WriteLine(operation); 64 Console.WriteLine(operation);
66 cmd = operation.Split(sep)[0]; 65 cmd = operation.Split(sep)[0];
67 switch(cmd) { 66 switch(cmd) {
68 case "connect_to_gridserver": 67 case "connect_to_gridserver":
69 win.SetStatus("Connecting to grid server..."); 68 win.SetStatus("Connecting to grid server...");
70 if(gridserverConn.Connect(operation.Split(sep)[1],operation.Split(sep)[2],operation.Split(sep)[3])) { 69 if(gridserverConn.Connect(operation.Split(sep)[1],operation.Split(sep)[2],operation.Split(sep)[3])) {
71 win.SetStatus("Connected OK with session ID:" + gridserverConn.SessionID); 70 win.SetStatus("Connected OK with session ID:" + gridserverConn.SessionID);
72 win.SetGridServerConnected(true); 71 win.SetGridServerConnected(true);
73 Thread.Sleep(3000); 72 Thread.Sleep(3000);
74 win.SetStatus("Downloading region maps..."); 73 win.SetStatus("Downloading region maps...");
75 gridserverConn.DownloadMap(); 74 gridserverConn.DownloadMap();
76 } else { 75 } else {
77 win.SetStatus("Could not connect"); 76 win.SetStatus("Could not connect");
78 } 77 }
79 break; 78 break;
80 79
81 case "restart_gridserver": 80 case "restart_gridserver":
82 win.SetStatus("Restarting grid server..."); 81 win.SetStatus("Restarting grid server...");
83 if(gridserverConn.RestartServer()) { 82 if(gridserverConn.RestartServer()) {
84 win.SetStatus("Restarted server OK"); 83 win.SetStatus("Restarted server OK");
85 Thread.Sleep(3000); 84 Thread.Sleep(3000);
86 win.SetStatus(""); 85 win.SetStatus("");
87 } else { 86 } else {
88 win.SetStatus("Error restarting grid server!!!"); 87 win.SetStatus("Error restarting grid server!!!");
89 } 88 }
90 break; 89 break;
91 90
92 case "shutdown_gridserver": 91 case "shutdown_gridserver":
93 win.SetStatus("Shutting down grid server..."); 92 win.SetStatus("Shutting down grid server...");
94 if(gridserverConn.ShutdownServer()) { 93 if(gridserverConn.ShutdownServer()) {
95 win.SetStatus("Grid server shutdown"); 94 win.SetStatus("Grid server shutdown");
96 win.SetGridServerConnected(false); 95 win.SetGridServerConnected(false);
97 Thread.Sleep(3000); 96 Thread.Sleep(3000);
98 win.SetStatus(""); 97 win.SetStatus("");
99 } else { 98 } else {
100 win.SetStatus("Could not shutdown grid server!!!"); 99 win.SetStatus("Could not shutdown grid server!!!");
101 } 100 }
102 break; 101 break;
103 102
104 case "disconnect_gridserver": 103 case "disconnect_gridserver":
105 gridserverConn.DisconnectServer(); 104 gridserverConn.DisconnectServer();
106 win.SetGridServerConnected(false); 105 win.SetGridServerConnected(false);
107 break; 106 break;
108 } 107 }
109 } 108 }
110 } 109 }
111 110
112 public static void Main (string[] args) 111 public static void Main (string[] args)
113 { 112 {
114 gridserverConn = new GridServerConnectionManager(); 113 gridserverConn = new GridServerConnectionManager();
115 Application.Init (); 114 Application.Init ();
116 win = new MainWindow (); 115 win = new MainWindow ();
117 win.Show (); 116 win.Show ();
118 OperationsRunner = new Thread(new ThreadStart(RunOperations)); 117 OperationsRunner = new Thread(new ThreadStart(RunOperations));
119 OperationsRunner.IsBackground=true; 118 OperationsRunner.IsBackground=true;
120 OperationsRunner.Start(); 119 OperationsRunner.Start();
121 DoMainLoop(); 120 DoMainLoop();
122 } 121 }
123 } 122 }
124} 123}
diff --git a/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs b/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs
index b9efe1d..312c347 100644
--- a/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs
+++ b/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs
@@ -29,76 +29,76 @@
29using System; 29using System;
30using Gtk; 30using Gtk;
31 31
32namespace OpenGridServices.Manager { 32namespace OpenGridServices.Manager
33 public partial class MainWindow: Gtk.Window 33{
34 { 34 public partial class MainWindow: Gtk.Window
35 public MainWindow (): base (Gtk.WindowType.Toplevel) 35 {
36 { 36 public MainWindow (): base (Gtk.WindowType.Toplevel)
37 Build (); 37 {
38 } 38 Build();
39 39 }
40 public void SetStatus(string statustext)
41 {
42 this.statusbar1.Pop(0);
43 this.statusbar1.Push(0,statustext);
44 }
45 40
46 public void DrawGrid(RegionBlock[][] regions) 41 public void SetStatus(string statustext)
47 { 42 {
48 for(int x=0; x<=regions.GetUpperBound(0); x++) { 43 this.statusbar1.Pop(0);
49 for(int y=0; y<=regions.GetUpperBound(1); y++) { 44 this.statusbar1.Push(0, statustext);
50 Gdk.Image themap = new Gdk.Image(Gdk.ImageType.Fastest,Gdk.Visual.System,256,256); 45 }
51 this.drawingarea1.GdkWindow.DrawImage(new Gdk.GC(this.drawingarea1.GdkWindow),themap,0,0,x*256,y*256,256,256);
52 }
53 }
54 }
55
56 public void SetGridServerConnected(bool connected)
57 {
58 if(connected) {
59 this.ConnectToGridserver.Visible=false;
60 this.DisconnectFromGridServer.Visible=true;
61 } else {
62 this.ConnectToGridserver.Visible=true;
63 this.DisconnectFromGridServer.Visible=false;
64 }
65 }
66
67 protected void OnDeleteEvent (object sender, DeleteEventArgs a)
68 {
69 Application.Quit ();
70 MainClass.QuitReq=true;
71 a.RetVal = true;
72 }
73
74 protected virtual void QuitMenu(object sender, System.EventArgs e)
75 {
76 MainClass.QuitReq=true;
77 Application.Quit();
78 }
79
80 protected virtual void ConnectToGridServerMenu(object sender, System.EventArgs e)
81 {
82 ConnectToGridServerDialog griddialog = new ConnectToGridServerDialog ();
83 griddialog.Show();
84 }
85 46
86 protected virtual void RestartGridserverMenu(object sender, System.EventArgs e) 47 public void DrawGrid(RegionBlock[][] regions)
87 { 48 {
88 MainClass.PendingOperations.Enqueue("restart_gridserver"); 49 for (int x=0; x<=regions.GetUpperBound(0); x++)
89 } 50 {
51 for (int y=0; y<=regions.GetUpperBound(1); y++)
52 {
53 Gdk.Image themap = new Gdk.Image(Gdk.ImageType.Fastest,Gdk.Visual.System,256,256);
54 this.drawingarea1.GdkWindow.DrawImage(new Gdk.GC(this.drawingarea1.GdkWindow),themap,0,0,x*256,y*256,256,256);
55 }
56 }
57 }
90 58
91 protected virtual void ShutdownGridserverMenu(object sender, System.EventArgs e) 59 public void SetGridServerConnected(bool connected)
92 { 60 {
93 MainClass.PendingOperations.Enqueue("shutdown_gridserver"); 61 if (connected) {
94 } 62 this.ConnectToGridserver.Visible=false;
63 this.DisconnectFromGridServer.Visible=true;
64 } else {
65 this.ConnectToGridserver.Visible=true;
66 this.DisconnectFromGridServer.Visible=false;
67 }
68 }
95 69
96 protected virtual void DisconnectGridServerMenu(object sender, System.EventArgs e) 70 protected void OnDeleteEvent (object sender, DeleteEventArgs a)
97 { 71 {
98 MainClass.PendingOperations.Enqueue("disconnect_gridserver"); 72 Application.Quit ();
99 } 73 MainClass.QuitReq=true;
74 a.RetVal = true;
75 }
100 76
101 } 77 protected virtual void QuitMenu(object sender, System.EventArgs e)
102} 78 {
79 MainClass.QuitReq=true;
80 Application.Quit();
81 }
82
83 protected virtual void ConnectToGridServerMenu(object sender, System.EventArgs e)
84 {
85 ConnectToGridServerDialog griddialog = new ConnectToGridServerDialog ();
86 griddialog.Show();
87 }
88
89 protected virtual void RestartGridserverMenu(object sender, System.EventArgs e)
90 {
91 MainClass.PendingOperations.Enqueue("restart_gridserver");
92 }
103 93
104 94 protected virtual void ShutdownGridserverMenu(object sender, System.EventArgs e)
95 {
96 MainClass.PendingOperations.Enqueue("shutdown_gridserver");
97 }
98
99 protected virtual void DisconnectGridServerMenu(object sender, System.EventArgs e)
100 {
101 MainClass.PendingOperations.Enqueue("disconnect_gridserver");
102 }
103 }
104}
diff --git a/OpenSim/Grid/Manager/OpenGridServices.Manager/RegionBlock.cs b/OpenSim/Grid/Manager/OpenGridServices.Manager/RegionBlock.cs
index 90e1ab6..ad28d65 100644
--- a/OpenSim/Grid/Manager/OpenGridServices.Manager/RegionBlock.cs
+++ b/OpenSim/Grid/Manager/OpenGridServices.Manager/RegionBlock.cs
@@ -33,33 +33,31 @@ using OpenSim.Framework.Utilities;
33 33
34namespace OpenGridServices.Manager 34namespace OpenGridServices.Manager
35{ 35{
36 36 public class RegionBlock
37 37 {
38 public class RegionBlock 38 public uint regloc_x;
39 { 39 public uint regloc_y;
40 public uint regloc_x;
41 public uint regloc_y;
42
43 public string httpd_url;
44
45 public string region_name;
46
47 public ulong regionhandle {
48 get { return Util.UIntsToLong(regloc_x*256,regloc_y*256); }
49 }
50 40
51 public Gdk.Pixbuf MiniMap; 41 public string httpd_url;
52
53 public RegionBlock()
54 {
55 }
56 42
57 public void LoadFromXmlNode(XmlNode sourcenode) 43 public string region_name;
58 { 44
59 this.regloc_x=Convert.ToUInt32(sourcenode.Attributes.GetNamedItem("loc_x").Value); 45 public ulong regionhandle {
60 this.regloc_y=Convert.ToUInt32(sourcenode.Attributes.GetNamedItem("loc_y").Value); 46 get { return Util.UIntsToLong(regloc_x*256,regloc_y*256); }
61 this.region_name=sourcenode.Attributes.GetNamedItem("region_name").Value; 47 }
62 this.httpd_url=sourcenode.Attributes.GetNamedItem("httpd_url").Value; 48
63 } 49 public Gdk.Pixbuf MiniMap;
64 } 50
51 public RegionBlock()
52 {
53 }
54
55 public void LoadFromXmlNode(XmlNode sourcenode)
56 {
57 this.regloc_x=Convert.ToUInt32(sourcenode.Attributes.GetNamedItem("loc_x").Value);
58 this.regloc_y=Convert.ToUInt32(sourcenode.Attributes.GetNamedItem("loc_y").Value);
59 this.region_name=sourcenode.Attributes.GetNamedItem("region_name").Value;
60 this.httpd_url=sourcenode.Attributes.GetNamedItem("httpd_url").Value;
61 }
62 }
65} 63}