home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 139 / dpcs0999.iso / Web / CFserver / data1.cab / Webroot / classes / CFGraphs / multibarchart.class (.txt) < prev    next >
Encoding:
Java Class File  |  1999-04-12  |  9.1 KB  |  550 lines

  1. import allaire.dcf.recordset.AppletParamRecordset;
  2. import allaire.dcf.recordset.Query;
  3. import allaire.dcf.recordset.Recordset;
  4. import allaire.util.Debug;
  5. import java.applet.Applet;
  6. import java.awt.Color;
  7. import java.awt.Component;
  8. import java.awt.Event;
  9. import java.awt.Font;
  10. import java.awt.FontMetrics;
  11. import java.awt.Graphics;
  12. import java.util.Date;
  13. import java.util.Vector;
  14.  
  15. public class MultiBarChart extends Applet implements Runnable {
  16.    static final int VERTICAL = 1;
  17.    static final int HORIZONTAL = 2;
  18.    static final int PARAMS = 1;
  19.    static final int TEMPLATE = 2;
  20.    static final Color[] defaultColors;
  21.    Thread runner;
  22.    Query query;
  23.    int refreshTime;
  24.    boolean debugInfoEnabled;
  25.    String title;
  26.    String titleFontName;
  27.    Font titleFont;
  28.    FontMetrics titleFontMetrics;
  29.    int titleFontHeight;
  30.    String legendFontName;
  31.    Font legendFont;
  32.    FontMetrics legendFontMetrics;
  33.    int legendFontHeight;
  34.    int legendHeight;
  35.    int legendWidth;
  36.    boolean legendEnabled;
  37.    int orientation;
  38.    int shadow;
  39.    boolean barBorderEnabled;
  40.    boolean showDateTime;
  41.    String currentDateTime;
  42.    Color backgroundColor;
  43.    Color fontColor;
  44.    Color lineColor;
  45.    Vector itemColors;
  46.    Vector itemLabels;
  47.    Vector pointerToItems;
  48.    Recordset chartData;
  49.    int rowCount;
  50.    int groupCount;
  51.    int itemCount;
  52.    int maxItemLabelWidth;
  53.    int maxGroupLabelWidth;
  54.    double maxGroupSum;
  55.  
  56.    public void start() {
  57.       if (this.runner == null) {
  58.          this.runner = new Thread(this);
  59.          this.runner.start();
  60.       }
  61.  
  62.    }
  63.  
  64.    public void stop() {
  65.       if (this.runner != null) {
  66.          this.runner.stop();
  67.          this.runner = null;
  68.       }
  69.  
  70.    }
  71.  
  72.    private void getData(int var1) {
  73.       try {
  74.          switch (var1) {
  75.             case 1:
  76.                this.chartData = new AppletParamRecordset(this, "ChartData");
  77.                break;
  78.             case 2:
  79.                this.query.execute();
  80.                this.chartData = this.query.getRecordset();
  81.          }
  82.  
  83.          if (this.refreshTime == 0) {
  84.             ((Applet)this).getAppletContext().showStatus("Done");
  85.          } else {
  86.             ((Applet)this).getAppletContext().showStatus("...");
  87.          }
  88.  
  89.          this.rowCount = this.chartData.getRowCount();
  90.          if (this.rowCount != 0) {
  91.             this.maxGroupSum = (double)0.0F;
  92.             double var7 = (double)0.0F;
  93.  
  94.             for(int var2 = 0; var2 < this.rowCount; ++var2) {
  95.                double var5;
  96.                try {
  97.                   var5 = Math.abs(new Double(this.chartData.getData(var2 + 1, "Values")));
  98.                } catch (Exception var11) {
  99.                   var5 = (double)0.0F;
  100.                }
  101.  
  102.                if (var2 == 0) {
  103.                   this.groupCount = this.itemCount = 1;
  104.                   this.pointerToItems.setSize(this.rowCount);
  105.                   this.pointerToItems.setElementAt(new Integer(this.itemCount - 1), var2);
  106.                   this.itemLabels.setSize(var2 + 1);
  107.                   this.itemLabels.setElementAt(this.chartData.getData(var2 + 1, "Items"), var2);
  108.                   this.maxItemLabelWidth = this.legendFontMetrics.stringWidth(this.chartData.getData(var2 + 1, "Items"));
  109.                   this.maxGroupLabelWidth = this.legendFontMetrics.stringWidth(this.chartData.getData(var2 + 1, "Groups"));
  110.                } else {
  111.                   if (!this.chartData.getData(var2 + 1, "Groups").equals(this.chartData.getData(var2, "Groups"))) {
  112.                      if (this.maxGroupSum < var7) {
  113.                         this.maxGroupSum = var7;
  114.                      }
  115.  
  116.                      this.maxGroupLabelWidth = Math.max(this.legendFontMetrics.stringWidth(this.chartData.getData(var2 + 1, "Groups")), this.maxGroupLabelWidth);
  117.                      var7 = (double)0.0F;
  118.                      ++this.groupCount;
  119.                   }
  120.  
  121.                   boolean var4 = false;
  122.  
  123.                   for(int var3 = 0; var3 < var2; ++var3) {
  124.                      if (this.chartData.getData(var2 + 1, "Items").equals(this.chartData.getData(var3 + 1, "Items"))) {
  125.                         var4 = true;
  126.                         this.pointerToItems.setElementAt(this.pointerToItems.elementAt(var3), var2);
  127.                         break;
  128.                      }
  129.                   }
  130.  
  131.                   if (!var4) {
  132.                      ++this.itemCount;
  133.                      this.pointerToItems.setElementAt(new Integer(this.itemCount - 1), var2);
  134.                      this.itemLabels.setSize(this.itemCount);
  135.                      this.itemLabels.setElementAt(this.chartData.getData(var2 + 1, "Items"), this.itemCount - 1);
  136.                      this.maxItemLabelWidth = Math.max(this.legendFontMetrics.stringWidth(this.chartData.getData(var2 + 1, "Items")), this.maxItemLabelWidth);
  137.                   }
  138.                }
  139.  
  140.                var7 += var5;
  141.             }
  142.  
  143.             if (this.maxGroupSum < var7) {
  144.                this.maxGroupSum = var7;
  145.             }
  146.  
  147.             this.itemColors.setSize(this.itemCount);
  148.  
  149.             for(int var13 = 0; var13 < this.itemCount; ++var13) {
  150.                if (var13 < 9) {
  151.                   this.itemColors.setElementAt(defaultColors[var13], var13);
  152.                } else if (var13 < 18) {
  153.                   this.itemColors.setElementAt(defaultColors[var13 - 9].darker(), var13);
  154.                } else if (var13 < 27) {
  155.                   this.itemColors.setElementAt(defaultColors[var13 - 18].darker().darker(), var13);
  156.                } else {
  157.                   this.itemColors.setElementAt(Color.black, var13);
  158.                }
  159.             }
  160.          }
  161.  
  162.          this.currentDateTime = (new Date()).toLocaleString();
  163.       } catch (Exception var12) {
  164.          if (this.debugInfoEnabled) {
  165.             Debug.write(((Throwable)var12).getMessage());
  166.          }
  167.  
  168.       }
  169.    }
  170.  
  171.    public boolean mouseExit(Event var1, int var2, int var3) {
  172.       if (var1.id == 505) {
  173.          ((Applet)this).getAppletContext().showStatus("");
  174.          return true;
  175.       } else {
  176.          return false;
  177.       }
  178.    }
  179.  
  180.    static {
  181.       defaultColors = new Color[]{Color.red, Color.blue, Color.green, Color.yellow, Color.magenta, Color.cyan, Color.orange, Color.pink, Color.darkGray};
  182.    }
  183.  
  184.    private void pause(int var1) {
  185.       try {
  186.          Thread.sleep((long)var1);
  187.       } catch (InterruptedException var4) {
  188.          if (this.debugInfoEnabled) {
  189.             Debug.write(((Throwable)var4).getMessage());
  190.          }
  191.  
  192.       }
  193.    }
  194.  
  195.    public boolean mouseEnter(Event var1, int var2, int var3) {
  196.       if (var1.id == 504) {
  197.          ((Applet)this).getAppletContext().showStatus("(c)1996 Allaire Corp.");
  198.          return true;
  199.       } else {
  200.          return false;
  201.       }
  202.    }
  203.  
  204.    public void run() {
  205.       while(this.refreshTime != 0) {
  206.          this.pause(this.refreshTime * 1000);
  207.          this.getData(2);
  208.          ((Component)this).repaint();
  209.       }
  210.  
  211.       this.stop();
  212.    }
  213.  
  214.    public synchronized void init() {
  215.       String var1 = ((Applet)this).getParameter("RefreshTime");
  216.       if (var1 == null) {
  217.          this.refreshTime = 0;
  218.       } else {
  219.          this.refreshTime = Integer.parseInt(var1);
  220.          var1 = ((Applet)this).getParameter("RefreshDataFromURL");
  221.          if (var1 == null) {
  222.             this.refreshTime = 0;
  223.          } else {
  224.             if (var1.indexOf(63) == -1) {
  225.                var1 = var1 + '?';
  226.             }
  227.  
  228.             this.query = new Query(var1);
  229.             this.query.addParam("RefreshTime", String.valueOf(this.refreshTime));
  230.          }
  231.       }
  232.  
  233.       var1 = ((Applet)this).getParameter("DebugInfoEnabled");
  234.       if (var1 == null) {
  235.          this.debugInfoEnabled = false;
  236.       } else if (var1.toLowerCase().equals("yes")) {
  237.          this.debugInfoEnabled = true;
  238.       } else {
  239.          this.debugInfoEnabled = false;
  240.       }
  241.  
  242.       this.title = ((Applet)this).getParameter("Title");
  243.       if (this.title == null) {
  244.          this.title = "Chart";
  245.       }
  246.  
  247.       this.titleFontName = ((Applet)this).getParameter("TitleFontName");
  248.       if (this.titleFontName == null) {
  249.          this.titleFontName = "TimesRoman";
  250.       }
  251.  
  252.       var1 = ((Applet)this).getParameter("TitleFontHeight");
  253.       if (var1 == null) {
  254.          this.titleFontHeight = 12;
  255.       } else {
  256.          this.titleFontHeight = Integer.parseInt(var1);
  257.       }
  258.  
  259.       this.legendFontName = ((Applet)this).getParameter("LegendFontName");
  260.       if (this.legendFontName == null) {
  261.          this.legendFontName = "TimesRoman";
  262.       }
  263.  
  264.       var1 = ((Applet)this).getParameter("ShowLegend");
  265.       if (var1 == null) {
  266.          this.legendEnabled = true;
  267.       } else if (var1.toLowerCase().equals("yes")) {
  268.          this.legendEnabled = true;
  269.       } else {
  270.          this.legendEnabled = false;
  271.       }
  272.  
  273.       var1 = ((Applet)this).getParameter("LegendFontHeight");
  274.       if (var1 == null) {
  275.          this.legendFontHeight = 10;
  276.       } else {
  277.          this.legendFontHeight = Integer.parseInt(var1);
  278.       }
  279.  
  280.       var1 = ((Applet)this).getParameter("DrawBorders");
  281.       if (var1 == null) {
  282.          this.barBorderEnabled = true;
  283.       } else if (var1.toLowerCase().equals("yes")) {
  284.          this.barBorderEnabled = true;
  285.       } else {
  286.          this.barBorderEnabled = false;
  287.       }
  288.  
  289.       var1 = ((Applet)this).getParameter("ShowDateTime");
  290.       if (var1 == null) {
  291.          this.showDateTime = true;
  292.       } else if (var1.toLowerCase().equals("yes")) {
  293.          this.showDateTime = true;
  294.       } else {
  295.          this.showDateTime = false;
  296.       }
  297.  
  298.       var1 = ((Applet)this).getParameter("Orientation");
  299.       if (var1 == null) {
  300.          this.orientation = 1;
  301.       } else if (var1.toLowerCase().equals("vertical")) {
  302.          this.orientation = 1;
  303.       } else if (var1.toLowerCase().equals("horizontal")) {
  304.          this.orientation = 2;
  305.       } else {
  306.          this.orientation = 1;
  307.       }
  308.  
  309.       var1 = ((Applet)this).getParameter("Shadow");
  310.       if (var1 == null) {
  311.          this.shadow = 4;
  312.       } else {
  313.          this.shadow = Integer.parseInt(var1);
  314.       }
  315.  
  316.       var1 = ((Applet)this).getParameter("BackgroundColor");
  317.       if (var1 == null) {
  318.          this.backgroundColor = ((Component)this).getBackground();
  319.       } else {
  320.          this.backgroundColor = new Color(Integer.valueOf(var1, 16));
  321.       }
  322.  
  323.       var1 = ((Applet)this).getParameter("FontColor");
  324.       if (var1 == null) {
  325.          this.fontColor = Color.black;
  326.       } else {
  327.          this.fontColor = new Color(Integer.valueOf(var1, 16));
  328.       }
  329.  
  330.       var1 = ((Applet)this).getParameter("GridLineColor");
  331.       if (var1 == null) {
  332.          this.lineColor = Color.gray;
  333.       } else {
  334.          this.lineColor = new Color(Integer.valueOf(var1, 16));
  335.       }
  336.  
  337.       ((Component)this).setBackground(this.backgroundColor);
  338.       this.titleFont = new Font(this.titleFontName, 1, this.titleFontHeight);
  339.       this.titleFontMetrics = ((Component)this).getFontMetrics(this.titleFont);
  340.       this.legendFont = new Font(this.legendFontName, 0, this.legendFontHeight);
  341.       this.legendFontMetrics = ((Component)this).getFontMetrics(this.legendFont);
  342.       this.pointerToItems = new Vector();
  343.       this.itemColors = new Vector();
  344.       this.itemLabels = new Vector();
  345.       this.getData(1);
  346.    }
  347.  
  348.    public synchronized void paint(Graphics var1) {
  349.       double var26 = (double)0.0F;
  350.       double var28 = (double)0.0F;
  351.       if (this.itemCount > 0) {
  352.          if (this.maxGroupSum == (double)0.0F) {
  353.             this.maxGroupSum = (double)1.0F;
  354.          }
  355.  
  356.          int var3 = ((Component)this).size().width / 15;
  357.          int var4 = ((Component)this).size().height / 15;
  358.          double var11 = Math.pow((double)10.0F, Math.floor(Math.log(this.maxGroupSum) / Math.log((double)10.0F)));
  359.          if (this.maxGroupSum / var11 < (double)2.0F) {
  360.             var11 /= (double)10.0F;
  361.          }
  362.  
  363.          if (this.maxGroupSum / var11 < (double)6.0F) {
  364.             var11 /= (double)2.0F;
  365.          }
  366.  
  367.          var1.setColor(this.fontColor);
  368.          var1.setFont(this.titleFont);
  369.          var1.drawString(this.title, Math.max((((Component)this).size().width - this.titleFontMetrics.stringWidth(this.title)) / 2, 0), ((Component)this).size().height - var4);
  370.          var1.setFont(this.legendFont);
  371.          if (this.showDateTime) {
  372.             var1.drawString("(as of " + this.currentDateTime + ")", Math.max((((Component)this).size().width - this.legendFontMetrics.stringWidth("(as of " + this.currentDateTime + ")")) / 2, 0), ((Component)this).size().height - var4 + this.legendFontHeight * 3 / 2);
  373.          }
  374.  
  375.          int var22;
  376.          if (this.legendEnabled) {
  377.             int var51 = Math.min((((Component)this).size().height - this.titleFontHeight - 3 * var4) / this.legendFontHeight, this.itemCount);
  378.             int var52 = (((Component)this).size().height - this.titleFontHeight - 3 * var4) / var51;
  379.             if (var52 > 2 * this.titleFontHeight) {
  380.                var52 = 2 * this.titleFontHeight;
  381.             }
  382.  
  383.             var22 = this.legendFontHeight * 2 + this.maxItemLabelWidth + var3;
  384.             int var50 = var51 * var52;
  385.             int var9 = ((Component)this).size().width - var22;
  386.             int var10 = (((Component)this).size().height - 3 * var4 - this.titleFontHeight - var50) / 2 + var4;
  387.             var1.drawRect(var9 - this.legendFontHeight, var10 - var52 / 2, var22 - var3 + 2 * this.legendFontHeight, var50 + var52 / 2);
  388.  
  389.             for(int var2 = 0; var2 < var51; ++var2) {
  390.                var1.setColor((Color)this.itemColors.elementAt(var2));
  391.                var1.fillRect(var9, var10, this.legendFontHeight, this.legendFontHeight);
  392.                if (this.barBorderEnabled) {
  393.                   var1.setColor(this.fontColor);
  394.                   var1.drawRect(var9, var10, this.legendFontHeight - 1, this.legendFontHeight - 1);
  395.                }
  396.  
  397.                var1.setColor(this.fontColor);
  398.                var1.drawString((String)this.itemLabels.elementAt(var2), var9 + 2 * this.legendFontHeight, var10 + this.legendFontHeight - 1);
  399.                var10 += var52;
  400.             }
  401.          } else {
  402.             boolean var25 = false;
  403.             boolean var24 = false;
  404.             boolean var23 = false;
  405.             var22 = 0;
  406.          }
  407.  
  408.          switch (this.orientation) {
  409.             case 1:
  410.                int var48 = ((Component)this).size().width - 2 * var3 - var22;
  411.                int var49 = ((Component)this).size().height - this.titleFontHeight - this.legendFontHeight - 3 * var4;
  412.                double var44 = Math.max((double)var49 / this.maxGroupSum, (double)0.0F);
  413.                int var46 = Math.max(var48 * 3 / (4 * this.groupCount), this.legendFontMetrics.stringWidth("O"));
  414.                int var47 = Math.max((var48 - this.groupCount * var46) / this.groupCount, 0);
  415.                int var39 = var3;
  416.                int var42 = var4 + var49;
  417.  
  418.                for(double var43 = (double)0.0F; var43 < this.maxGroupSum; var43 += var11) {
  419.                   var1.setColor(this.lineColor);
  420.                   var1.drawLine(var39, var42 - (int)(var44 * var43), var39 + var48, var42 - (int)(var44 * var43));
  421.                   var1.drawString("" + var43, var39 - this.legendFontMetrics.stringWidth("" + var43) - 2, var42 - (int)(var44 * var43) + this.legendFontHeight / 2);
  422.                }
  423.  
  424.                var39 += var47 / 2 + this.shadow;
  425.                int var45 = 0;
  426.                int var8 = 0;
  427.                var28 = (double)0.0F;
  428.                String var57 = "";
  429.  
  430.                for(int var38 = 0; var38 < this.rowCount; ++var38) {
  431.                   String var56;
  432.                   try {
  433.                      var56 = this.chartData.getData(var38 + 1, "Groups");
  434.                   } catch (Exception var36) {
  435.                      var56 = "";
  436.                   }
  437.  
  438.                   if (var38 > 0) {
  439.                      if (!var56.equals(var57)) {
  440.                         if (this.legendFontMetrics.stringWidth(var57) > var46) {
  441.                            var57 = var57.substring(0, var57.length() * var46 / this.legendFontMetrics.stringWidth(var57));
  442.                         }
  443.  
  444.                         var1.drawString("" + var28, var39 + (var46 - this.legendFontMetrics.stringWidth("" + var28)) / 2, var42 - var8 - var45 - 3);
  445.                         var1.drawString(var57, var39 + (var46 - this.legendFontMetrics.stringWidth(var57)) / 2, var42 + this.legendFontHeight + this.shadow);
  446.                         var8 = 0;
  447.                         var28 = (double)0.0F;
  448.                         var39 += var46 + var47;
  449.                      } else {
  450.                         var8 += var45;
  451.                      }
  452.                   }
  453.  
  454.                   var57 = var56;
  455.  
  456.                   try {
  457.                      var26 = new Double(this.chartData.getData(var38 + 1, "Values"));
  458.                   } catch (Exception var35) {
  459.                      var26 = (double)0.0F;
  460.                   }
  461.  
  462.                   var28 += Math.abs(var26);
  463.                   var45 = (int)Math.abs(var44 * var26);
  464.                   var1.setColor(this.lineColor);
  465.                   var1.fillRect(var39, var42 - var8 - var45, var46, var45 + 1);
  466.                   var1.setColor((Color)this.itemColors.elementAt((Integer)this.pointerToItems.elementAt(var38)));
  467.                   var1.fillRect(var39 - this.shadow, var42 - var8 - var45 + this.shadow, var46, var45 + 1);
  468.                   var1.setColor(this.fontColor);
  469.                   if (this.barBorderEnabled) {
  470.                      var1.drawRect(var39 - this.shadow, var42 - var8 - var45 + this.shadow, var46 - 1, var45);
  471.                   }
  472.                }
  473.  
  474.                if (this.legendFontMetrics.stringWidth(var57) > var46) {
  475.                   var57 = var57.substring(0, var57.length() * var46 / this.legendFontMetrics.stringWidth(var57));
  476.                }
  477.  
  478.                var1.drawString("" + var28, var39 + (var46 - this.legendFontMetrics.stringWidth("" + var26)) / 2, var42 - var8 - var45 - 3);
  479.                var1.drawString(var57, var39 + (var46 - this.legendFontMetrics.stringWidth(var57)) / 2, var42 + this.legendFontHeight + this.shadow);
  480.                return;
  481.             case 2:
  482.                int var20 = ((Component)this).size().width - 2 * var3 - var22 - this.maxGroupLabelWidth;
  483.                int var21 = ((Component)this).size().height - this.titleFontHeight - this.legendFontHeight - 2 * var4;
  484.                double var15 = Math.max((double)var20 / this.maxGroupSum, (double)0.0F);
  485.                int var18 = var21 * 3 / (4 * this.groupCount);
  486.                int var19 = Math.max((var21 - this.groupCount * var18) / this.groupCount, 0);
  487.                int var5 = var3 + this.maxGroupLabelWidth + this.shadow;
  488.                int var6 = var4;
  489.  
  490.                for(double var13 = (double)0.0F; var13 < this.maxGroupSum; var13 += var11) {
  491.                   var1.setColor(this.lineColor);
  492.                   var1.drawLine(var5 + (int)(var15 * var13), var6, var5 + (int)(var15 * var13), var6 + var21);
  493.                   var1.drawString("" + var13, var5 + (int)(var15 * var13) - this.legendFontMetrics.stringWidth("" + var13) / 2, var6 - 2);
  494.                }
  495.  
  496.                var6 += var19 / 2 + this.shadow;
  497.                int var17 = 0;
  498.                int var7 = 0;
  499.                var28 = (double)0.0F;
  500.                String var31 = "";
  501.  
  502.                for(int var37 = 0; var37 < this.rowCount; ++var37) {
  503.                   String var30;
  504.                   try {
  505.                      var30 = this.chartData.getData(var37 + 1, "Groups");
  506.                   } catch (Exception var34) {
  507.                      var30 = "";
  508.                   }
  509.  
  510.                   if (var37 > 0) {
  511.                      if (!var30.equals(var31)) {
  512.                         var1.drawString("" + var28, var5 + var7 + var17 + 4, var6 + var18 / 2 + this.legendFontHeight / 2 - this.shadow);
  513.                         var1.drawString(var31, var3 - var3 / 3, var6 + var18 / 2 + this.legendFontHeight / 2 - this.shadow);
  514.                         var7 = 0;
  515.                         var28 = (double)0.0F;
  516.                         var6 += var18 + var19;
  517.                      } else {
  518.                         var7 += var17;
  519.                      }
  520.                   }
  521.  
  522.                   var31 = var30;
  523.  
  524.                   try {
  525.                      var26 = new Double(this.chartData.getData(var37 + 1, "Values"));
  526.                   } catch (Exception var33) {
  527.                      var26 = (double)0.0F;
  528.                   }
  529.  
  530.                   var28 += Math.abs(var26);
  531.                   var17 = (int)Math.abs(var15 * var26);
  532.                   var1.setColor(this.lineColor);
  533.                   var1.fillRect(var5 + var7, var6, var17 + 1, var18);
  534.                   var1.setColor((Color)this.itemColors.elementAt((Integer)this.pointerToItems.elementAt(var37)));
  535.                   var1.fillRect(var5 + var7 - this.shadow, var6 - this.shadow, var17 + 1, var18);
  536.                   var1.setColor(this.fontColor);
  537.                   if (this.barBorderEnabled) {
  538.                      var1.drawRect(var5 + var7 - this.shadow, var6 - this.shadow, var17, var18 - 1);
  539.                   }
  540.                }
  541.  
  542.                var1.drawString("" + var28, var5 + var7 + var17 + 4, var6 + var18 / 2 + this.legendFontHeight / 2 - this.shadow);
  543.                var1.drawString(var31, var3 - var3 / 3, var6 + var18 / 2 + this.legendFontHeight / 2 - this.shadow);
  544.                return;
  545.          }
  546.       }
  547.  
  548.    }
  549. }
  550.